SqlView, SqlSp, SqlFunction kaldırıldı
This commit is contained in:
parent
a87c06c2ff
commit
fe19cacedc
33 changed files with 552 additions and 4808 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
|
|
@ -6,38 +5,20 @@ using Volo.Abp.Application.Services;
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unified service for SQL Object Explorer and CRUD operations
|
/// SQL Query Manager - executes T-SQL and provides database metadata.
|
||||||
|
/// Does not persist SQL objects to its own tables.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISqlObjectManagerAppService : IApplicationService
|
public interface ISqlObjectManagerAppService : IApplicationService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all SQL objects for Object Explorer (Queries, SPs, Views, Functions, Tables, Templates)
|
/// Returns tables (and optionally templates) available on the given data source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataSourceCode">Data source code to filter objects</param>
|
|
||||||
/// <returns>Combined response with all object types</returns>
|
|
||||||
Task<SqlObjectExplorerDto> GetAllObjectsAsync(string dataSourceCode);
|
Task<SqlObjectExplorerDto> GetAllObjectsAsync(string dataSourceCode);
|
||||||
|
|
||||||
// Query Operations
|
/// <summary>
|
||||||
Task<SqlQueryDto> CreateQueryAsync(CreateSqlQueryDto input);
|
/// Executes raw T-SQL against the specified data source.
|
||||||
Task<SqlQueryDto> UpdateQueryAsync(Guid id, UpdateSqlQueryDto input);
|
/// </summary>
|
||||||
Task DeleteQueryAsync(Guid id);
|
|
||||||
Task<SqlQueryExecutionResultDto> ExecuteQueryAsync(ExecuteSqlQueryDto input);
|
Task<SqlQueryExecutionResultDto> ExecuteQueryAsync(ExecuteSqlQueryDto input);
|
||||||
Task<SqlQueryExecutionResultDto> ExecuteSavedQueryAsync(Guid id);
|
|
||||||
|
|
||||||
// Stored Procedure Operations
|
|
||||||
Task<SqlStoredProcedureDto> UpdateStoredProcedureAsync(Guid id, UpdateSqlStoredProcedureDto input);
|
|
||||||
Task DeleteStoredProcedureAsync(Guid id);
|
|
||||||
Task<SqlQueryExecutionResultDto> DeployStoredProcedureAsync(DeployStoredProcedureDto input);
|
|
||||||
|
|
||||||
// View Operations
|
|
||||||
Task<SqlViewDto> UpdateViewAsync(Guid id, UpdateSqlViewDto input);
|
|
||||||
Task DeleteViewAsync(Guid id);
|
|
||||||
Task<SqlQueryExecutionResultDto> DeployViewAsync(DeployViewDto input);
|
|
||||||
|
|
||||||
// Function Operations
|
|
||||||
Task<SqlFunctionDto> UpdateFunctionAsync(Guid id, UpdateSqlFunctionDto input);
|
|
||||||
Task DeleteFunctionAsync(Guid id);
|
|
||||||
Task<SqlQueryExecutionResultDto> DeployFunctionAsync(DeployFunctionDto input);
|
|
||||||
|
|
||||||
// Database Metadata Operations
|
// Database Metadata Operations
|
||||||
Task<List<DatabaseColumnDto>> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName);
|
Task<List<DatabaseColumnDto>> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName);
|
||||||
|
|
@ -46,7 +27,4 @@ public interface ISqlObjectManagerAppService : IApplicationService
|
||||||
/// Gets the SQL definition/body of a native SQL Server object (Stored Procedure, View, or Function)
|
/// Gets the SQL definition/body of a native SQL Server object (Stored Procedure, View, or Function)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<string> GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName);
|
Task<string> GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName);
|
||||||
|
|
||||||
// Smart Save - Analyzes SQL and saves to appropriate table with auto-deploy
|
|
||||||
Task<SmartSaveResultDto> SmartSaveAsync(SmartSaveInputDto input);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Input for smart save operation
|
|
||||||
/// </summary>
|
|
||||||
public class SmartSaveInputDto
|
|
||||||
{
|
|
||||||
public string SqlText { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Result of smart save operation
|
|
||||||
/// </summary>
|
|
||||||
public class SmartSaveResultDto
|
|
||||||
{
|
|
||||||
public string ObjectType { get; set; }
|
|
||||||
public Guid ObjectId { get; set; }
|
|
||||||
public bool Deployed { get; set; }
|
|
||||||
public string Message { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
||||||
|
|
||||||
|
public class ExecuteSqlQueryDto
|
||||||
|
{
|
||||||
|
public string QueryText { get; set; }
|
||||||
|
public string DataSourceCode { get; set; }
|
||||||
|
public Dictionary<string, object> Parameters { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SqlQueryExecutionResultDto
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public IEnumerable<dynamic> Data { get; set; }
|
||||||
|
public int RowsAffected { get; set; }
|
||||||
|
public long ExecutionTimeMs { get; set; }
|
||||||
|
public Dictionary<string, object> Metadata { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
|
||||||
|
|
||||||
public class SqlFunctionDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
public string FunctionName { get; set; }
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public SqlFunctionType FunctionType { get; set; }
|
|
||||||
public string FunctionBody { get; set; }
|
|
||||||
public string ReturnType { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public bool IsDeployed { get; set; }
|
|
||||||
public DateTime? LastDeployedAt { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
public bool IsCustom { get; set; } // true = stored in database, false = native SQL Server object
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CreateSqlFunctionDto
|
|
||||||
{
|
|
||||||
public string FunctionName { get; set; }
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public SqlFunctionType FunctionType { get; set; }
|
|
||||||
public string FunctionBody { get; set; }
|
|
||||||
public string ReturnType { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateSqlFunctionDto
|
|
||||||
{
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string FunctionBody { get; set; }
|
|
||||||
public string ReturnType { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DeployFunctionDto
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public bool DropIfExists { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -3,37 +3,23 @@ using System.Collections.Generic;
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Combined DTO for Object Explorer containing all SQL objects
|
/// A native SQL Server object (view, stored procedure, or function) discovered from system catalogs.
|
||||||
|
/// </summary>
|
||||||
|
public class SqlNativeObjectDto
|
||||||
|
{
|
||||||
|
public string SchemaName { get; set; } = "dbo";
|
||||||
|
public string ObjectName { get; set; } = "";
|
||||||
|
public string FullName => $"[{SchemaName}].[{ObjectName}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Object Explorer DTO - reflects the live SQL Server catalog structure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SqlObjectExplorerDto
|
public class SqlObjectExplorerDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// SQL Queries
|
|
||||||
/// </summary>
|
|
||||||
public List<SqlQueryDto> Queries { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stored Procedures
|
|
||||||
/// </summary>
|
|
||||||
public List<SqlStoredProcedureDto> StoredProcedures { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Views
|
|
||||||
/// </summary>
|
|
||||||
public List<SqlViewDto> Views { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Functions
|
|
||||||
/// </summary>
|
|
||||||
public List<SqlFunctionDto> Functions { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Database Tables
|
|
||||||
/// </summary>
|
|
||||||
public List<DatabaseTableDto> Tables { get; set; } = new();
|
public List<DatabaseTableDto> Tables { get; set; } = new();
|
||||||
|
public List<SqlNativeObjectDto> Views { get; set; } = new();
|
||||||
/// <summary>
|
public List<SqlNativeObjectDto> StoredProcedures { get; set; } = new();
|
||||||
/// Query Templates
|
public List<SqlNativeObjectDto> Functions { get; set; } = new();
|
||||||
/// </summary>
|
|
||||||
public List<SqlTemplateDto> Templates { get; set; } = new();
|
public List<SqlTemplateDto> Templates { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
|
||||||
|
|
||||||
public class SqlQueryDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
public string Code { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string QueryText { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Tags { get; set; }
|
|
||||||
public DateTime? LastExecutedAt { get; set; }
|
|
||||||
public int ExecutionCount { get; set; }
|
|
||||||
public bool IsModifyingData { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CreateSqlQueryDto
|
|
||||||
{
|
|
||||||
public string Code { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string QueryText { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Tags { get; set; }
|
|
||||||
public bool IsModifyingData { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateSqlQueryDto
|
|
||||||
{
|
|
||||||
public string Code { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string QueryText { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Tags { get; set; }
|
|
||||||
public bool IsModifyingData { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ExecuteSqlQueryDto
|
|
||||||
{
|
|
||||||
public string QueryText { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public Dictionary<string, object> Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SqlQueryExecutionResultDto
|
|
||||||
{
|
|
||||||
public bool Success { get; set; }
|
|
||||||
public string Message { get; set; }
|
|
||||||
public IEnumerable<dynamic> Data { get; set; }
|
|
||||||
public int RowsAffected { get; set; }
|
|
||||||
public long ExecutionTimeMs { get; set; }
|
|
||||||
public Dictionary<string, object> Metadata { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
|
||||||
|
|
||||||
public class SqlStoredProcedureDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
public string ProcedureName { get; set; }
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string ProcedureBody { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public bool IsDeployed { get; set; }
|
|
||||||
public DateTime? LastDeployedAt { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
public bool IsCustom { get; set; } // true = stored in database, false = native SQL Server object
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CreateSqlStoredProcedureDto
|
|
||||||
{
|
|
||||||
public string ProcedureName { get; set; }
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string ProcedureBody { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateSqlStoredProcedureDto
|
|
||||||
{
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string ProcedureBody { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DeployStoredProcedureDto
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public bool DropIfExists { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Application.Contracts;
|
|
||||||
|
|
||||||
public class SqlViewDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
public string ViewName { get; set; }
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string ViewDefinition { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public bool IsDeployed { get; set; }
|
|
||||||
public DateTime? LastDeployedAt { get; set; }
|
|
||||||
public bool WithSchemaBinding { get; set; }
|
|
||||||
public bool IsCustom { get; set; } // true = stored in database, false = native SQL Server object
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CreateSqlViewDto
|
|
||||||
{
|
|
||||||
public string ViewName { get; set; }
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string ViewDefinition { get; set; }
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public bool WithSchemaBinding { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateSqlViewDto
|
|
||||||
{
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string ViewDefinition { get; set; }
|
|
||||||
public string Category { get; set; }
|
|
||||||
public bool WithSchemaBinding { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DeployViewDto
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public bool DropIfExists { get; set; }
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,88 +1,12 @@
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Sozsoft.SqlQueryManager.Application.Contracts;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Entities;
|
|
||||||
using Volo.Abp.AutoMapper;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Application;
|
namespace Sozsoft.SqlQueryManager.Application;
|
||||||
|
|
||||||
|
// No entity-to-DTO mappings needed; SQL objects are no longer persisted in this module.
|
||||||
public class SqlQueryManagerAutoMapperProfile : Profile
|
public class SqlQueryManagerAutoMapperProfile : Profile
|
||||||
{
|
{
|
||||||
public SqlQueryManagerAutoMapperProfile()
|
public SqlQueryManagerAutoMapperProfile()
|
||||||
{
|
{
|
||||||
CreateMap<SqlQuery, SqlQueryDto>();
|
// intentionally empty
|
||||||
CreateMap<CreateSqlQueryDto, SqlQuery>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.LastExecutedAt)
|
|
||||||
.Ignore(x => x.ExecutionCount);
|
|
||||||
|
|
||||||
CreateMap<UpdateSqlQueryDto, SqlQuery>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.LastExecutedAt)
|
|
||||||
.Ignore(x => x.ExecutionCount);
|
|
||||||
|
|
||||||
CreateMap<SqlStoredProcedure, SqlStoredProcedureDto>().Ignore(x => x.IsCustom);
|
|
||||||
CreateMap<CreateSqlStoredProcedureDto, SqlStoredProcedure>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.IsDeployed)
|
|
||||||
.Ignore(x => x.LastDeployedAt);
|
|
||||||
|
|
||||||
CreateMap<UpdateSqlStoredProcedureDto, SqlStoredProcedure>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.ProcedureName)
|
|
||||||
.Ignore(x => x.SchemaName)
|
|
||||||
.Ignore(x => x.DataSourceCode)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.IsDeployed)
|
|
||||||
.Ignore(x => x.LastDeployedAt);
|
|
||||||
|
|
||||||
CreateMap<SqlView, SqlViewDto>().Ignore(x => x.IsCustom);
|
|
||||||
CreateMap<CreateSqlViewDto, SqlView>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.IsDeployed)
|
|
||||||
.Ignore(x => x.LastDeployedAt);
|
|
||||||
CreateMap<UpdateSqlViewDto, SqlView>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.ViewName)
|
|
||||||
.Ignore(x => x.SchemaName)
|
|
||||||
.Ignore(x => x.DataSourceCode)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.IsDeployed)
|
|
||||||
.Ignore(x => x.LastDeployedAt);
|
|
||||||
|
|
||||||
CreateMap<SqlFunction, SqlFunctionDto>().Ignore(x => x.IsCustom);
|
|
||||||
CreateMap<CreateSqlFunctionDto, SqlFunction>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.IsDeployed)
|
|
||||||
.Ignore(x => x.LastDeployedAt);
|
|
||||||
CreateMap<UpdateSqlFunctionDto, SqlFunction>()
|
|
||||||
.IgnoreFullAuditedObjectProperties()
|
|
||||||
.Ignore(x => x.Id)
|
|
||||||
.Ignore(x => x.TenantId)
|
|
||||||
.Ignore(x => x.FunctionName)
|
|
||||||
.Ignore(x => x.SchemaName)
|
|
||||||
.Ignore(x => x.FunctionType)
|
|
||||||
.Ignore(x => x.DataSourceCode)
|
|
||||||
.Ignore(x => x.Status)
|
|
||||||
.Ignore(x => x.IsDeployed)
|
|
||||||
.Ignore(x => x.LastDeployedAt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,4 @@
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Shared;
|
namespace Sozsoft.SqlQueryManager.Domain.Shared;
|
||||||
|
|
||||||
public enum SqlObjectType
|
// SqlObjectType, SqlFunctionType and SqlQueryStatus enums removed:
|
||||||
{
|
// The module no longer persists SQL objects and therefore does not need these enums.
|
||||||
Query = 1,
|
|
||||||
StoredProcedure = 2,
|
|
||||||
View = 3,
|
|
||||||
Function = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SqlFunctionType
|
|
||||||
{
|
|
||||||
ScalarFunction = 1,
|
|
||||||
TableValuedFunction = 2,
|
|
||||||
InlineTableValuedFunction = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SqlQueryStatus
|
|
||||||
{
|
|
||||||
Draft = 1,
|
|
||||||
Active = 2,
|
|
||||||
Archived = 3
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,50 +6,12 @@ public static class SqlQueryManagerPermissions
|
||||||
{
|
{
|
||||||
public const string GroupName = "SqlQueryManager";
|
public const string GroupName = "SqlQueryManager";
|
||||||
|
|
||||||
public static class SqlQuery
|
public static class SqlExecution
|
||||||
{
|
{
|
||||||
public const string Default = GroupName + ".SqlQuery";
|
public const string Default = GroupName + ".SqlExecution";
|
||||||
public const string Create = Default + ".Create";
|
|
||||||
public const string Update = Default + ".Update";
|
|
||||||
public const string Delete = Default + ".Delete";
|
|
||||||
public const string Execute = Default + ".Execute";
|
public const string Execute = Default + ".Execute";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SqlStoredProcedure
|
|
||||||
{
|
|
||||||
public const string Default = GroupName + ".SqlStoredProcedure";
|
|
||||||
public const string Create = Default + ".Create";
|
|
||||||
public const string Update = Default + ".Update";
|
|
||||||
public const string Delete = Default + ".Delete";
|
|
||||||
public const string Deploy = Default + ".Deploy";
|
|
||||||
public const string Drop = Default + ".Drop";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SqlView
|
|
||||||
{
|
|
||||||
public const string Default = GroupName + ".SqlView";
|
|
||||||
public const string Create = Default + ".Create";
|
|
||||||
public const string Update = Default + ".Update";
|
|
||||||
public const string Delete = Default + ".Delete";
|
|
||||||
public const string Deploy = Default + ".Deploy";
|
|
||||||
public const string Drop = Default + ".Drop";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SqlFunction
|
|
||||||
{
|
|
||||||
public const string Default = GroupName + ".SqlFunction";
|
|
||||||
public const string Create = Default + ".Create";
|
|
||||||
public const string Update = Default + ".Update";
|
|
||||||
public const string Delete = Default + ".Delete";
|
|
||||||
public const string Deploy = Default + ".Deploy";
|
|
||||||
public const string Drop = Default + ".Drop";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Templates
|
|
||||||
{
|
|
||||||
public const string Default = GroupName + ".Templates";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] GetAll()
|
public static string[] GetAll()
|
||||||
{
|
{
|
||||||
return ReflectionHelper.GetPublicConstantsRecursively(typeof(SqlQueryManagerPermissions));
|
return ReflectionHelper.GetPublicConstantsRecursively(typeof(SqlQueryManagerPermissions));
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
using System;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
|
||||||
using Volo.Abp.MultiTenancy;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Entities;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL Function entity for creating and managing database functions
|
|
||||||
/// </summary>
|
|
||||||
public class SqlFunction : FullAuditedEntity<Guid>, IMultiTenant
|
|
||||||
{
|
|
||||||
public Guid? TenantId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Function name in database
|
|
||||||
/// </summary>
|
|
||||||
public string FunctionName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Schema name (default: dbo)
|
|
||||||
/// </summary>
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Display name
|
|
||||||
/// </summary>
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Description
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Function type
|
|
||||||
/// </summary>
|
|
||||||
public SqlFunctionType FunctionType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Full function definition (CREATE/ALTER)
|
|
||||||
/// </summary>
|
|
||||||
public string FunctionBody { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Return type definition
|
|
||||||
/// </summary>
|
|
||||||
public string ReturnType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DataSource code
|
|
||||||
/// </summary>
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Status
|
|
||||||
/// </summary>
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Category
|
|
||||||
/// </summary>
|
|
||||||
public string Category { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether function exists in database
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDeployed { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Last deployment time
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? LastDeployedAt { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parameter definitions (JSON)
|
|
||||||
/// </summary>
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
|
|
||||||
protected SqlFunction()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqlFunction(
|
|
||||||
Guid id,
|
|
||||||
string functionName,
|
|
||||||
string schemaName,
|
|
||||||
string displayName,
|
|
||||||
SqlFunctionType functionType,
|
|
||||||
string functionBody,
|
|
||||||
string returnType,
|
|
||||||
string dataSourceCode,
|
|
||||||
Guid? tenantId = null) : base(id)
|
|
||||||
{
|
|
||||||
FunctionName = functionName;
|
|
||||||
SchemaName = schemaName ?? "dbo";
|
|
||||||
DisplayName = displayName;
|
|
||||||
FunctionType = functionType;
|
|
||||||
FunctionBody = functionBody;
|
|
||||||
ReturnType = returnType;
|
|
||||||
DataSourceCode = dataSourceCode;
|
|
||||||
TenantId = tenantId;
|
|
||||||
Status = SqlQueryStatus.Draft;
|
|
||||||
IsDeployed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateBody(string body)
|
|
||||||
{
|
|
||||||
FunctionBody = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkAsDeployed()
|
|
||||||
{
|
|
||||||
IsDeployed = true;
|
|
||||||
LastDeployedAt = DateTime.UtcNow;
|
|
||||||
Status = SqlQueryStatus.Active;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetFullName() => $"{SchemaName}.{FunctionName}";
|
|
||||||
}
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
using System;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
|
||||||
using Volo.Abp.MultiTenancy;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Entities;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL Query entity for storing and managing SQL queries
|
|
||||||
/// </summary>
|
|
||||||
public class SqlQuery : FullAuditedEntity<Guid>, IMultiTenant
|
|
||||||
{
|
|
||||||
public Guid? TenantId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unique code for the query
|
|
||||||
/// </summary>
|
|
||||||
public string Code { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Display name
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Description of the query
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL query content
|
|
||||||
/// </summary>
|
|
||||||
public string QueryText { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DataSource code to use for execution
|
|
||||||
/// </summary>
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Query status
|
|
||||||
/// </summary>
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Category for organization
|
|
||||||
/// </summary>
|
|
||||||
public string Category { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tags for filtering
|
|
||||||
/// </summary>
|
|
||||||
public string Tags { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Last execution time
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? LastExecutedAt { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Execution count
|
|
||||||
/// </summary>
|
|
||||||
public int ExecutionCount { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether query modifies data
|
|
||||||
/// </summary>
|
|
||||||
public bool IsModifyingData { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Expected parameter definitions (JSON format)
|
|
||||||
/// </summary>
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
|
|
||||||
protected SqlQuery()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqlQuery(
|
|
||||||
Guid id,
|
|
||||||
string code,
|
|
||||||
string name,
|
|
||||||
string queryText,
|
|
||||||
string dataSourceCode,
|
|
||||||
Guid? tenantId = null) : base(id)
|
|
||||||
{
|
|
||||||
Code = code;
|
|
||||||
Name = name;
|
|
||||||
QueryText = queryText;
|
|
||||||
DataSourceCode = dataSourceCode;
|
|
||||||
TenantId = tenantId;
|
|
||||||
Status = SqlQueryStatus.Draft;
|
|
||||||
ExecutionCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateQueryText(string queryText)
|
|
||||||
{
|
|
||||||
QueryText = queryText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkAsExecuted()
|
|
||||||
{
|
|
||||||
LastExecutedAt = DateTime.UtcNow;
|
|
||||||
ExecutionCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Activate()
|
|
||||||
{
|
|
||||||
Status = SqlQueryStatus.Active;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Archive()
|
|
||||||
{
|
|
||||||
Status = SqlQueryStatus.Archived;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
using System;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
|
||||||
using Volo.Abp.MultiTenancy;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Entities;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL Stored Procedure entity for creating and managing stored procedures
|
|
||||||
/// </summary>
|
|
||||||
public class SqlStoredProcedure : FullAuditedEntity<Guid>, IMultiTenant
|
|
||||||
{
|
|
||||||
public Guid? TenantId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Procedure name in database
|
|
||||||
/// </summary>
|
|
||||||
public string ProcedureName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Schema name (default: dbo)
|
|
||||||
/// </summary>
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Display name
|
|
||||||
/// </summary>
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Description
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Full procedure definition (CREATE/ALTER)
|
|
||||||
/// </summary>
|
|
||||||
public string ProcedureBody { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DataSource code
|
|
||||||
/// </summary>
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Status
|
|
||||||
/// </summary>
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Category
|
|
||||||
/// </summary>
|
|
||||||
public string Category { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether procedure exists in database
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDeployed { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Last deployment time
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? LastDeployedAt { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parameter definitions (JSON)
|
|
||||||
/// </summary>
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
|
|
||||||
protected SqlStoredProcedure()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqlStoredProcedure(
|
|
||||||
Guid id,
|
|
||||||
string procedureName,
|
|
||||||
string schemaName,
|
|
||||||
string displayName,
|
|
||||||
string procedureBody,
|
|
||||||
string dataSourceCode,
|
|
||||||
Guid? tenantId = null) : base(id)
|
|
||||||
{
|
|
||||||
ProcedureName = procedureName;
|
|
||||||
SchemaName = schemaName ?? "dbo";
|
|
||||||
DisplayName = displayName;
|
|
||||||
ProcedureBody = procedureBody;
|
|
||||||
DataSourceCode = dataSourceCode;
|
|
||||||
TenantId = tenantId;
|
|
||||||
Status = SqlQueryStatus.Draft;
|
|
||||||
IsDeployed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateBody(string body)
|
|
||||||
{
|
|
||||||
ProcedureBody = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkAsDeployed()
|
|
||||||
{
|
|
||||||
IsDeployed = true;
|
|
||||||
LastDeployedAt = DateTime.UtcNow;
|
|
||||||
Status = SqlQueryStatus.Active;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetFullName() => $"{SchemaName}.{ProcedureName}";
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
using System;
|
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
|
||||||
using Volo.Abp.MultiTenancy;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Entities;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL View entity for creating and managing database views
|
|
||||||
/// </summary>
|
|
||||||
public class SqlView : FullAuditedEntity<Guid>, IMultiTenant
|
|
||||||
{
|
|
||||||
public Guid? TenantId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// View name in database
|
|
||||||
/// </summary>
|
|
||||||
public string ViewName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Schema name (default: dbo)
|
|
||||||
/// </summary>
|
|
||||||
public string SchemaName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Display name
|
|
||||||
/// </summary>
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Description
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// View definition (SELECT statement)
|
|
||||||
/// </summary>
|
|
||||||
public string ViewDefinition { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DataSource code
|
|
||||||
/// </summary>
|
|
||||||
public string DataSourceCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Status
|
|
||||||
/// </summary>
|
|
||||||
public SqlQueryStatus Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Category
|
|
||||||
/// </summary>
|
|
||||||
public string Category { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether view exists in database
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDeployed { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Last deployment time
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? LastDeployedAt { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether to use WITH SCHEMABINDING
|
|
||||||
/// </summary>
|
|
||||||
public bool WithSchemaBinding { get; set; }
|
|
||||||
|
|
||||||
protected SqlView()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqlView(
|
|
||||||
Guid id,
|
|
||||||
string viewName,
|
|
||||||
string schemaName,
|
|
||||||
string displayName,
|
|
||||||
string viewDefinition,
|
|
||||||
string dataSourceCode,
|
|
||||||
Guid? tenantId = null) : base(id)
|
|
||||||
{
|
|
||||||
ViewName = viewName;
|
|
||||||
SchemaName = schemaName ?? "dbo";
|
|
||||||
DisplayName = displayName;
|
|
||||||
ViewDefinition = viewDefinition;
|
|
||||||
DataSourceCode = dataSourceCode;
|
|
||||||
TenantId = tenantId;
|
|
||||||
Status = SqlQueryStatus.Draft;
|
|
||||||
IsDeployed = false;
|
|
||||||
WithSchemaBinding = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateDefinition(string definition)
|
|
||||||
{
|
|
||||||
ViewDefinition = definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkAsDeployed()
|
|
||||||
{
|
|
||||||
IsDeployed = true;
|
|
||||||
LastDeployedAt = DateTime.UtcNow;
|
|
||||||
Status = SqlQueryStatus.Active;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetFullName() => $"{SchemaName}.{ViewName}";
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Services;
|
namespace Sozsoft.SqlQueryManager.Domain.Services;
|
||||||
|
|
@ -22,75 +22,28 @@ public class SqlExecutionResult
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Service for executing SQL commands
|
/// Service for executing T-SQL commands against configured data sources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISqlExecutorService
|
public interface ISqlExecutorService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Execute a SELECT query and return results.</summary>
|
||||||
/// Execute a SELECT query and return results
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> ExecuteQueryAsync(
|
Task<SqlExecutionResult> ExecuteQueryAsync(
|
||||||
string sql,
|
string sql,
|
||||||
string dataSourceCode,
|
string dataSourceCode,
|
||||||
Dictionary<string, object> parameters = null);
|
Dictionary<string, object> parameters = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Execute a non-query command (INSERT, UPDATE, DELETE, DDL).</summary>
|
||||||
/// Execute a non-query command (INSERT, UPDATE, DELETE)
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> ExecuteNonQueryAsync(
|
Task<SqlExecutionResult> ExecuteNonQueryAsync(
|
||||||
string sql,
|
string sql,
|
||||||
string dataSourceCode,
|
string dataSourceCode,
|
||||||
Dictionary<string, object> parameters = null);
|
Dictionary<string, object> parameters = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Execute scalar query (returns single value).</summary>
|
||||||
/// Execute scalar query (returns single value)
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> ExecuteScalarAsync<T>(
|
Task<SqlExecutionResult> ExecuteScalarAsync<T>(
|
||||||
string sql,
|
string sql,
|
||||||
string dataSourceCode,
|
string dataSourceCode,
|
||||||
Dictionary<string, object> parameters = null);
|
Dictionary<string, object> parameters = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Validate SQL syntax (basic validation).</summary>
|
||||||
/// Deploy stored procedure to database
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> DeployStoredProcedureAsync(
|
|
||||||
string procedureBody,
|
|
||||||
string dataSourceCode);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deploy view to database
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> DeployViewAsync(
|
|
||||||
string viewDefinition,
|
|
||||||
string dataSourceCode);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deploy function to database
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> DeployFunctionAsync(
|
|
||||||
string functionBody,
|
|
||||||
string dataSourceCode);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if database object exists
|
|
||||||
/// </summary>
|
|
||||||
Task<bool> CheckObjectExistsAsync(
|
|
||||||
string objectName,
|
|
||||||
string objectType,
|
|
||||||
string dataSourceCode,
|
|
||||||
string schemaName = "dbo");
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Drop database object
|
|
||||||
/// </summary>
|
|
||||||
Task<SqlExecutionResult> DropObjectAsync(
|
|
||||||
string objectName,
|
|
||||||
string objectType,
|
|
||||||
string dataSourceCode,
|
|
||||||
string schemaName = "dbo");
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validate SQL syntax (basic validation)
|
|
||||||
/// </summary>
|
|
||||||
Task<(bool IsValid, string ErrorMessage)> ValidateSqlAsync(string sql);
|
Task<(bool IsValid, string ErrorMessage)> ValidateSqlAsync(string sql);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Services;
|
namespace Sozsoft.SqlQueryManager.Domain.Services;
|
||||||
|
|
||||||
|
|
@ -8,29 +7,21 @@ namespace Sozsoft.SqlQueryManager.Domain.Services;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISqlTemplateProvider
|
public interface ISqlTemplateProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Get stored procedure template.</summary>
|
||||||
/// Get stored procedure template
|
|
||||||
/// </summary>
|
|
||||||
string GetStoredProcedureTemplate(string procedureName, string schemaName = "dbo");
|
string GetStoredProcedureTemplate(string procedureName, string schemaName = "dbo");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Get view template.</summary>
|
||||||
/// Get view template
|
|
||||||
/// </summary>
|
|
||||||
string GetViewTemplate(string viewName, string schemaName = "dbo", bool withSchemaBinding = false);
|
string GetViewTemplate(string viewName, string schemaName = "dbo", bool withSchemaBinding = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get function template
|
/// Get function template. functionType: "Scalar" | "TableValued" | "InlineTableValued"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string GetFunctionTemplate(string functionName, SqlFunctionType functionType, string schemaName = "dbo");
|
string GetFunctionTemplate(string functionName, string functionType = "Scalar", string schemaName = "dbo");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Get query template with common patterns.</summary>
|
||||||
/// Get query template with common patterns
|
|
||||||
/// </summary>
|
|
||||||
string GetQueryTemplate(string queryType);
|
string GetQueryTemplate(string queryType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Get available query template types.</summary>
|
||||||
/// Get available query template types
|
|
||||||
/// </summary>
|
|
||||||
List<QueryTemplateInfo> GetAvailableQueryTemplates();
|
List<QueryTemplateInfo> GetAvailableQueryTemplates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,81 +179,6 @@ public class SqlExecutorService : DomainService, ISqlExecutorService
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SqlExecutionResult> DeployStoredProcedureAsync(
|
|
||||||
string procedureBody,
|
|
||||||
string dataSourceCode)
|
|
||||||
{
|
|
||||||
return await ExecuteNonQueryAsync(procedureBody, dataSourceCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<SqlExecutionResult> DeployViewAsync(
|
|
||||||
string viewDefinition,
|
|
||||||
string dataSourceCode)
|
|
||||||
{
|
|
||||||
return await ExecuteNonQueryAsync(viewDefinition, dataSourceCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<SqlExecutionResult> DeployFunctionAsync(
|
|
||||||
string functionBody,
|
|
||||||
string dataSourceCode)
|
|
||||||
{
|
|
||||||
return await ExecuteNonQueryAsync(functionBody, dataSourceCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> CheckObjectExistsAsync(
|
|
||||||
string objectName,
|
|
||||||
string objectType,
|
|
||||||
string dataSourceCode,
|
|
||||||
string schemaName = "dbo")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var sql = $@"
|
|
||||||
SELECT COUNT(*)
|
|
||||||
FROM sys.objects o
|
|
||||||
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
||||||
WHERE s.name = @SchemaName
|
|
||||||
AND o.name = @ObjectName
|
|
||||||
AND o.type_desc = @ObjectType";
|
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "SchemaName", schemaName },
|
|
||||||
{ "ObjectName", objectName },
|
|
||||||
{ "ObjectType", objectType.ToUpperInvariant() }
|
|
||||||
};
|
|
||||||
|
|
||||||
var result = await ExecuteScalarAsync<int>(sql, dataSourceCode, parameters);
|
|
||||||
|
|
||||||
return result.Success && result.Metadata.ContainsKey("ScalarValue")
|
|
||||||
&& Convert.ToInt32(result.Metadata["ScalarValue"]) > 0;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<SqlExecutionResult> DropObjectAsync(
|
|
||||||
string objectName,
|
|
||||||
string objectType,
|
|
||||||
string dataSourceCode,
|
|
||||||
string schemaName = "dbo")
|
|
||||||
{
|
|
||||||
var dropCommand = objectType.ToUpperInvariant() switch
|
|
||||||
{
|
|
||||||
"SQL_STORED_PROCEDURE" => $"DROP PROCEDURE IF EXISTS [{schemaName}].[{objectName}]",
|
|
||||||
"VIEW" => $"DROP VIEW IF EXISTS [{schemaName}].[{objectName}]",
|
|
||||||
"SQL_SCALAR_FUNCTION" => $"DROP FUNCTION IF EXISTS [{schemaName}].[{objectName}]",
|
|
||||||
"SQL_TABLE_VALUED_FUNCTION" => $"DROP FUNCTION IF EXISTS [{schemaName}].[{objectName}]",
|
|
||||||
"SQL_INLINE_TABLE_VALUED_FUNCTION" => $"DROP FUNCTION IF EXISTS [{schemaName}].[{objectName}]",
|
|
||||||
_ => throw new BusinessException("SqlQueryManager:UnsupportedObjectType")
|
|
||||||
.WithData("ObjectType", objectType)
|
|
||||||
};
|
|
||||||
|
|
||||||
return await ExecuteNonQueryAsync(dropCommand, dataSourceCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<(bool IsValid, string ErrorMessage)> ValidateSqlAsync(string sql)
|
public Task<(bool IsValid, string ErrorMessage)> ValidateSqlAsync(string sql)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -299,3 +224,4 @@ public class SqlExecutorService : DomainService, ISqlExecutorService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Sozsoft.SqlQueryManager.Domain.Shared;
|
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.Domain.Services;
|
namespace Sozsoft.SqlQueryManager.Domain.Services;
|
||||||
|
|
@ -70,13 +69,12 @@ AS
|
||||||
GO";
|
GO";
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetFunctionTemplate(string functionName, SqlFunctionType functionType, string schemaName = "dbo")
|
public string GetFunctionTemplate(string functionName, string functionType = "Scalar", string schemaName = "dbo")
|
||||||
{
|
{
|
||||||
return functionType switch
|
return functionType switch
|
||||||
{
|
{
|
||||||
SqlFunctionType.ScalarFunction => GetScalarFunctionTemplate(functionName, schemaName),
|
"TableValued" => GetTableValuedFunctionTemplate(functionName, schemaName),
|
||||||
SqlFunctionType.TableValuedFunction => GetTableValuedFunctionTemplate(functionName, schemaName),
|
"InlineTableValued" => GetInlineTableValuedFunctionTemplate(functionName, schemaName),
|
||||||
SqlFunctionType.InlineTableValuedFunction => GetInlineTableValuedFunctionTemplate(functionName, schemaName),
|
|
||||||
_ => GetScalarFunctionTemplate(functionName, schemaName)
|
_ => GetScalarFunctionTemplate(functionName, schemaName)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Sozsoft.SqlQueryManager.Domain.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Volo.Abp.Data;
|
using Volo.Abp.Data;
|
||||||
using Volo.Abp.EntityFrameworkCore;
|
using Volo.Abp.EntityFrameworkCore;
|
||||||
|
|
@ -8,11 +7,6 @@ namespace Sozsoft.SqlQueryManager.EntityFrameworkCore;
|
||||||
[ConnectionStringName("Default")]
|
[ConnectionStringName("Default")]
|
||||||
public class SqlQueryManagerDbContext : AbpDbContext<SqlQueryManagerDbContext>
|
public class SqlQueryManagerDbContext : AbpDbContext<SqlQueryManagerDbContext>
|
||||||
{
|
{
|
||||||
public DbSet<SqlQuery> SqlQueries { get; set; }
|
|
||||||
public DbSet<SqlStoredProcedure> SqlStoredProcedures { get; set; }
|
|
||||||
public DbSet<SqlView> SqlViews { get; set; }
|
|
||||||
public DbSet<SqlFunction> SqlFunctions { get; set; }
|
|
||||||
|
|
||||||
public SqlQueryManagerDbContext(DbContextOptions<SqlQueryManagerDbContext> options)
|
public SqlQueryManagerDbContext(DbContextOptions<SqlQueryManagerDbContext> options)
|
||||||
: base(options)
|
: base(options)
|
||||||
{
|
{
|
||||||
|
|
@ -21,7 +15,6 @@ public class SqlQueryManagerDbContext : AbpDbContext<SqlQueryManagerDbContext>
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(builder);
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
builder.ConfigureSqlQueryManager();
|
builder.ConfigureSqlQueryManager();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
using Sozsoft.SqlQueryManager.Domain.Entities;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Volo.Abp;
|
using Volo.Abp;
|
||||||
using Volo.Abp.EntityFrameworkCore.Modeling;
|
|
||||||
|
|
||||||
namespace Sozsoft.SqlQueryManager.EntityFrameworkCore;
|
namespace Sozsoft.SqlQueryManager.EntityFrameworkCore;
|
||||||
|
|
||||||
|
|
@ -10,95 +8,7 @@ public static class SqlQueryManagerDbContextModelCreatingExtensions
|
||||||
public static void ConfigureSqlQueryManager(this ModelBuilder builder)
|
public static void ConfigureSqlQueryManager(this ModelBuilder builder)
|
||||||
{
|
{
|
||||||
Check.NotNull(builder, nameof(builder));
|
Check.NotNull(builder, nameof(builder));
|
||||||
|
// SQL object entities (SqlQuery, SqlStoredProcedure, SqlView, SqlFunction) have been
|
||||||
// SqlQuery
|
// removed. The module no longer persists SQL objects to its own tables.
|
||||||
builder.Entity<SqlQuery>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(TablePrefix.ByName(nameof(SqlQuery)), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.Code).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.Name).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.Description).HasMaxLength(1024);
|
|
||||||
b.Property(x => x.QueryText).IsRequired();
|
|
||||||
b.Property(x => x.DataSourceCode).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.Status).IsRequired();
|
|
||||||
b.Property(x => x.Category).HasMaxLength(128);
|
|
||||||
b.Property(x => x.Tags).HasMaxLength(512);
|
|
||||||
b.Property(x => x.Parameters).HasMaxLength(4096);
|
|
||||||
|
|
||||||
b.HasIndex(x => x.Code);
|
|
||||||
b.HasIndex(x => x.DataSourceCode);
|
|
||||||
b.HasIndex(x => x.Status);
|
|
||||||
b.HasIndex(x => x.Category);
|
|
||||||
});
|
|
||||||
|
|
||||||
// SqlStoredProcedure
|
|
||||||
builder.Entity<SqlStoredProcedure>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(TablePrefix.ByName(nameof(SqlStoredProcedure)), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.ProcedureName).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.SchemaName).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.DisplayName).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.Description).HasMaxLength(1024);
|
|
||||||
b.Property(x => x.ProcedureBody).IsRequired();
|
|
||||||
b.Property(x => x.DataSourceCode).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.Status).IsRequired();
|
|
||||||
b.Property(x => x.Category).HasMaxLength(128);
|
|
||||||
b.Property(x => x.Parameters).HasMaxLength(4096);
|
|
||||||
|
|
||||||
b.HasIndex(x => new { x.SchemaName, x.ProcedureName });
|
|
||||||
b.HasIndex(x => x.DataSourceCode);
|
|
||||||
b.HasIndex(x => x.Status);
|
|
||||||
b.HasIndex(x => x.IsDeployed);
|
|
||||||
});
|
|
||||||
|
|
||||||
// SqlView
|
|
||||||
builder.Entity<SqlView>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(TablePrefix.ByName(nameof(SqlView)), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.ViewName).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.SchemaName).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.DisplayName).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.Description).HasMaxLength(1024);
|
|
||||||
b.Property(x => x.ViewDefinition).IsRequired();
|
|
||||||
b.Property(x => x.DataSourceCode).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.Status).IsRequired();
|
|
||||||
b.Property(x => x.Category).HasMaxLength(128);
|
|
||||||
|
|
||||||
b.HasIndex(x => new { x.SchemaName, x.ViewName });
|
|
||||||
b.HasIndex(x => x.DataSourceCode);
|
|
||||||
b.HasIndex(x => x.Status);
|
|
||||||
b.HasIndex(x => x.IsDeployed);
|
|
||||||
});
|
|
||||||
|
|
||||||
// SqlFunction
|
|
||||||
builder.Entity<SqlFunction>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(TablePrefix.ByName(nameof(SqlFunction)), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.FunctionName).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.SchemaName).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.DisplayName).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.Description).HasMaxLength(1024);
|
|
||||||
b.Property(x => x.FunctionType).IsRequired();
|
|
||||||
b.Property(x => x.FunctionBody).IsRequired();
|
|
||||||
b.Property(x => x.ReturnType).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.DataSourceCode).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.Status).IsRequired();
|
|
||||||
b.Property(x => x.Category).HasMaxLength(128);
|
|
||||||
b.Property(x => x.Parameters).HasMaxLength(4096);
|
|
||||||
|
|
||||||
b.HasIndex(x => new { x.SchemaName, x.FunctionName });
|
|
||||||
b.HasIndex(x => x.DataSourceCode);
|
|
||||||
b.HasIndex(x => x.Status);
|
|
||||||
b.HasIndex(x => x.FunctionType);
|
|
||||||
b.HasIndex(x => x.IsDeployed);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10254,6 +10254,12 @@
|
||||||
"tr": "Çalıştır",
|
"tr": "Çalıştır",
|
||||||
"en": "Execute"
|
"en": "Execute"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Platform.NewQuery",
|
||||||
|
"tr": "Yeni Sorgu",
|
||||||
|
"en": "New Query"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Platform.Save",
|
"key": "App.Platform.Save",
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,6 @@ public enum TableNameEnum
|
||||||
ForumPost,
|
ForumPost,
|
||||||
SqlTable,
|
SqlTable,
|
||||||
SqlTableField,
|
SqlTableField,
|
||||||
SqlView,
|
|
||||||
SqlStoredProcedure,
|
|
||||||
SqlFunction,
|
|
||||||
SqlQuery,
|
|
||||||
CrudEndpoint,
|
CrudEndpoint,
|
||||||
CustomEndpoint,
|
CustomEndpoint,
|
||||||
CustomComponent,
|
CustomComponent,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Sozsoft.Platform.Migrations
|
namespace Sozsoft.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20260302111924_Initial")]
|
[Migration("20260302174517_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -4486,409 +4486,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Sas_H_SettingDefinition", (string)null);
|
b.ToTable("Sas_H_SettingDefinition", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlFunction", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("FunctionBody")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("FunctionName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("FunctionType")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeployed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastDeployedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ReturnType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("SchemaName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("FunctionType");
|
|
||||||
|
|
||||||
b.HasIndex("IsDeployed");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.HasIndex("SchemaName", "FunctionName");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlFunction", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlQuery", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Code")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<int>("ExecutionCount")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsModifyingData")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastExecutedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("QueryText")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<string>("Tags")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("nvarchar(512)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("Category");
|
|
||||||
|
|
||||||
b.HasIndex("Code");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlQuery", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlStoredProcedure", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeployed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastDeployedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ProcedureBody")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ProcedureName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<string>("SchemaName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("IsDeployed");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.HasIndex("SchemaName", "ProcedureName");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlStoredProcedure", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlView", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeployed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastDeployedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("SchemaName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.Property<string>("ViewDefinition")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ViewName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<bool>("WithSchemaBinding")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("IsDeployed");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.HasIndex("SchemaName", "ViewName");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlView", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
|
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -986,99 +986,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table.PrimaryKey("PK_Adm_T_SkillType", x => x.Id);
|
table.PrimaryKey("PK_Adm_T_SkillType", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Adm_T_SqlFunction",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
FunctionName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
SchemaName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
|
||||||
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
|
||||||
FunctionType = table.Column<int>(type: "int", nullable: false),
|
|
||||||
FunctionBody = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
|
||||||
ReturnType = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
|
||||||
DataSourceCode = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
Status = table.Column<int>(type: "int", nullable: false),
|
|
||||||
Category = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
|
||||||
IsDeployed = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
LastDeployedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
Parameters = table.Column<string>(type: "nvarchar(max)", maxLength: 4096, nullable: true),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Adm_T_SqlFunction", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Adm_T_SqlQuery",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
Code = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
|
||||||
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
|
||||||
QueryText = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
|
||||||
DataSourceCode = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
Status = table.Column<int>(type: "int", nullable: false),
|
|
||||||
Category = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
|
||||||
Tags = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
|
|
||||||
LastExecutedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
ExecutionCount = table.Column<int>(type: "int", nullable: false),
|
|
||||||
IsModifyingData = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
Parameters = table.Column<string>(type: "nvarchar(max)", maxLength: 4096, nullable: true),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Adm_T_SqlQuery", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Adm_T_SqlStoredProcedure",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
ProcedureName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
SchemaName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
|
||||||
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
|
||||||
ProcedureBody = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
|
||||||
DataSourceCode = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
Status = table.Column<int>(type: "int", nullable: false),
|
|
||||||
Category = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
|
||||||
IsDeployed = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
LastDeployedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
Parameters = table.Column<string>(type: "nvarchar(max)", maxLength: 4096, nullable: true),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Adm_T_SqlStoredProcedure", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Adm_T_SqlTable",
|
name: "Adm_T_SqlTable",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -1107,36 +1014,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table.PrimaryKey("PK_Adm_T_SqlTable", x => x.Id);
|
table.PrimaryKey("PK_Adm_T_SqlTable", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Adm_T_SqlView",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
ViewName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
SchemaName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
|
||||||
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
|
||||||
ViewDefinition = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
|
||||||
DataSourceCode = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
Status = table.Column<int>(type: "int", nullable: false),
|
|
||||||
Category = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
|
||||||
IsDeployed = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
LastDeployedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
WithSchemaBinding = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Adm_T_SqlView", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Adm_T_UomCategory",
|
name: "Adm_T_UomCategory",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -2994,96 +2871,11 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table: "Adm_T_SkillLevel",
|
table: "Adm_T_SkillLevel",
|
||||||
column: "SkillTypeId");
|
column: "SkillTypeId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlFunction_DataSourceCode",
|
|
||||||
table: "Adm_T_SqlFunction",
|
|
||||||
column: "DataSourceCode");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlFunction_FunctionType",
|
|
||||||
table: "Adm_T_SqlFunction",
|
|
||||||
column: "FunctionType");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlFunction_IsDeployed",
|
|
||||||
table: "Adm_T_SqlFunction",
|
|
||||||
column: "IsDeployed");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlFunction_SchemaName_FunctionName",
|
|
||||||
table: "Adm_T_SqlFunction",
|
|
||||||
columns: new[] { "SchemaName", "FunctionName" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlFunction_Status",
|
|
||||||
table: "Adm_T_SqlFunction",
|
|
||||||
column: "Status");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlQuery_Category",
|
|
||||||
table: "Adm_T_SqlQuery",
|
|
||||||
column: "Category");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlQuery_Code",
|
|
||||||
table: "Adm_T_SqlQuery",
|
|
||||||
column: "Code");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlQuery_DataSourceCode",
|
|
||||||
table: "Adm_T_SqlQuery",
|
|
||||||
column: "DataSourceCode");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlQuery_Status",
|
|
||||||
table: "Adm_T_SqlQuery",
|
|
||||||
column: "Status");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlStoredProcedure_DataSourceCode",
|
|
||||||
table: "Adm_T_SqlStoredProcedure",
|
|
||||||
column: "DataSourceCode");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlStoredProcedure_IsDeployed",
|
|
||||||
table: "Adm_T_SqlStoredProcedure",
|
|
||||||
column: "IsDeployed");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlStoredProcedure_SchemaName_ProcedureName",
|
|
||||||
table: "Adm_T_SqlStoredProcedure",
|
|
||||||
columns: new[] { "SchemaName", "ProcedureName" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlStoredProcedure_Status",
|
|
||||||
table: "Adm_T_SqlStoredProcedure",
|
|
||||||
column: "Status");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Adm_T_SqlTableField_EntityId",
|
name: "IX_Adm_T_SqlTableField_EntityId",
|
||||||
table: "Adm_T_SqlTableField",
|
table: "Adm_T_SqlTableField",
|
||||||
column: "EntityId");
|
column: "EntityId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlView_DataSourceCode",
|
|
||||||
table: "Adm_T_SqlView",
|
|
||||||
column: "DataSourceCode");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlView_IsDeployed",
|
|
||||||
table: "Adm_T_SqlView",
|
|
||||||
column: "IsDeployed");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlView_SchemaName_ViewName",
|
|
||||||
table: "Adm_T_SqlView",
|
|
||||||
columns: new[] { "SchemaName", "ViewName" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Adm_T_SqlView_Status",
|
|
||||||
table: "Adm_T_SqlView",
|
|
||||||
column: "Status");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Adm_T_Uom_UomCategoryId",
|
name: "IX_Adm_T_Uom_UomCategoryId",
|
||||||
table: "Adm_T_Uom",
|
table: "Adm_T_Uom",
|
||||||
|
|
@ -3359,21 +3151,9 @@ namespace Sozsoft.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Adm_T_SkillLevel");
|
name: "Adm_T_SkillLevel");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Adm_T_SqlFunction");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Adm_T_SqlQuery");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Adm_T_SqlStoredProcedure");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Adm_T_SqlTableField");
|
name: "Adm_T_SqlTableField");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Adm_T_SqlView");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Adm_T_Uom");
|
name: "Adm_T_Uom");
|
||||||
|
|
||||||
|
|
@ -4483,409 +4483,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Sas_H_SettingDefinition", (string)null);
|
b.ToTable("Sas_H_SettingDefinition", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlFunction", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("FunctionBody")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("FunctionName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("FunctionType")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeployed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastDeployedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ReturnType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("SchemaName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("FunctionType");
|
|
||||||
|
|
||||||
b.HasIndex("IsDeployed");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.HasIndex("SchemaName", "FunctionName");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlFunction", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlQuery", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Code")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<int>("ExecutionCount")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsModifyingData")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastExecutedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("QueryText")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<string>("Tags")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("nvarchar(512)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("Category");
|
|
||||||
|
|
||||||
b.HasIndex("Code");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlQuery", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlStoredProcedure", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeployed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastDeployedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ProcedureBody")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ProcedureName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<string>("SchemaName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("IsDeployed");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.HasIndex("SchemaName", "ProcedureName");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlStoredProcedure", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlView", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Category")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<string>("DataSourceCode")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeployed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastDeployedAt")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("SchemaName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.Property<string>("ViewDefinition")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("ViewName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<bool>("WithSchemaBinding")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("DataSourceCode");
|
|
||||||
|
|
||||||
b.HasIndex("IsDeployed");
|
|
||||||
|
|
||||||
b.HasIndex("Status");
|
|
||||||
|
|
||||||
b.HasIndex("SchemaName", "ViewName");
|
|
||||||
|
|
||||||
b.ToTable("Adm_T_SqlView", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
|
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
|
||||||
|
|
@ -1,214 +1,10 @@
|
||||||
import type { FullAuditedEntityDto, PagedAndSortedResultRequestDto } from '../index'
|
// SQL Execution
|
||||||
|
|
||||||
export enum SqlObjectType {
|
|
||||||
Query = 1,
|
|
||||||
StoredProcedure = 2,
|
|
||||||
View = 3,
|
|
||||||
Function = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum SqlFunctionType {
|
|
||||||
ScalarFunction = 1,
|
|
||||||
TableValuedFunction = 2,
|
|
||||||
InlineTableValuedFunction = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum SqlQueryStatus {
|
|
||||||
Draft = 1,
|
|
||||||
Active = 2,
|
|
||||||
Archived = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
// SQL Function DTOs
|
|
||||||
export interface SqlFunctionDto extends FullAuditedEntityDto<string> {
|
|
||||||
functionName: string
|
|
||||||
schemaName: string
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
functionType: SqlFunctionType
|
|
||||||
functionBody: string
|
|
||||||
returnType: string
|
|
||||||
dataSourceCode: string
|
|
||||||
status: SqlQueryStatus
|
|
||||||
category: string
|
|
||||||
isDeployed: boolean
|
|
||||||
lastDeployedAt?: string
|
|
||||||
parameters: string
|
|
||||||
isCustom: boolean // true = stored in database, false = native SQL Server object
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateSqlFunctionDto {
|
|
||||||
functionName: string
|
|
||||||
schemaName: string
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
functionType: SqlFunctionType
|
|
||||||
functionBody: string
|
|
||||||
returnType: string
|
|
||||||
dataSourceCode: string
|
|
||||||
category: string
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateSqlFunctionDto {
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
functionBody: string
|
|
||||||
returnType: string
|
|
||||||
category: string
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DeployFunctionDto {
|
|
||||||
id: string
|
|
||||||
dropIfExists: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// SQL Query DTOs
|
|
||||||
export interface SqlQueryDto extends FullAuditedEntityDto<string> {
|
|
||||||
code: string
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
queryText: string
|
|
||||||
dataSourceCode: string
|
|
||||||
status: SqlQueryStatus
|
|
||||||
category: string
|
|
||||||
tags: string
|
|
||||||
lastExecutedAt?: string
|
|
||||||
executionCount: number
|
|
||||||
isModifyingData: boolean
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateSqlQueryDto {
|
|
||||||
code: string
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
queryText: string
|
|
||||||
dataSourceCode: string
|
|
||||||
category: string
|
|
||||||
tags: string
|
|
||||||
isModifyingData: boolean
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateSqlQueryDto {
|
|
||||||
code: string
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
queryText: string
|
|
||||||
dataSourceCode: string
|
|
||||||
category: string
|
|
||||||
tags: string
|
|
||||||
isModifyingData: boolean
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExecuteSqlQueryDto {
|
export interface ExecuteSqlQueryDto {
|
||||||
queryText: string
|
queryText: string
|
||||||
dataSourceCode: string
|
dataSourceCode: string
|
||||||
parameters?: Record<string, any>
|
parameters?: Record<string, any>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExecuteSavedQueryDto {
|
|
||||||
id: string
|
|
||||||
parameters?: Record<string, any>
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ValidateQueryDto {
|
|
||||||
queryText: string
|
|
||||||
dataSourceCode: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SQL Stored Procedure DTOs
|
|
||||||
export interface SqlStoredProcedureDto extends FullAuditedEntityDto<string> {
|
|
||||||
procedureName: string
|
|
||||||
schemaName: string
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
procedureBody: string
|
|
||||||
dataSourceCode: string
|
|
||||||
status: SqlQueryStatus
|
|
||||||
category: string
|
|
||||||
isDeployed: boolean
|
|
||||||
lastDeployedAt?: string
|
|
||||||
parameters: string
|
|
||||||
isCustom: boolean // true = stored in database, false = native SQL Server object
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateSqlStoredProcedureDto {
|
|
||||||
procedureName: string
|
|
||||||
schemaName: string
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
procedureBody: string
|
|
||||||
dataSourceCode: string
|
|
||||||
category: string
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateSqlStoredProcedureDto {
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
procedureBody: string
|
|
||||||
category: string
|
|
||||||
parameters: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DeployStoredProcedureDto {
|
|
||||||
id: string
|
|
||||||
dropIfExists: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// SQL View DTOs
|
|
||||||
export interface SqlViewDto extends FullAuditedEntityDto<string> {
|
|
||||||
viewName: string
|
|
||||||
schemaName: string
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
viewDefinition: string
|
|
||||||
dataSourceCode: string
|
|
||||||
status: SqlQueryStatus
|
|
||||||
category: string
|
|
||||||
isDeployed: boolean
|
|
||||||
lastDeployedAt?: string
|
|
||||||
withSchemaBinding: boolean
|
|
||||||
isCustom: boolean // true = stored in database, false = native SQL Server object
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateSqlViewDto {
|
|
||||||
viewName: string
|
|
||||||
schemaName: string
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
viewDefinition: string
|
|
||||||
dataSourceCode: string
|
|
||||||
category: string
|
|
||||||
withSchemaBinding: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateSqlViewDto {
|
|
||||||
displayName: string
|
|
||||||
description: string
|
|
||||||
viewDefinition: string
|
|
||||||
category: string
|
|
||||||
withSchemaBinding: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DeployViewDto {
|
|
||||||
id: string
|
|
||||||
dropIfExists: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// SQL Template DTOs
|
|
||||||
export interface SqlTemplateDto {
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
template: string
|
|
||||||
category: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SQL Execution Result
|
|
||||||
export interface SqlQueryExecutionResultDto {
|
export interface SqlQueryExecutionResultDto {
|
||||||
success: boolean
|
success: boolean
|
||||||
message: string
|
message: string
|
||||||
|
|
@ -219,42 +15,27 @@ export interface SqlQueryExecutionResultDto {
|
||||||
error?: string
|
error?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request DTOs
|
// SQL Templates
|
||||||
export interface GetSqlFunctionsInput extends PagedAndSortedResultRequestDto {
|
export interface SqlTemplateDto {
|
||||||
filter?: string
|
type: string
|
||||||
dataSourceCode?: string
|
name: string
|
||||||
status?: SqlQueryStatus
|
description: string
|
||||||
category?: string
|
template: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetSqlQueriesInput extends PagedAndSortedResultRequestDto {
|
// Database Metadata
|
||||||
filter?: string
|
|
||||||
dataSourceCode?: string
|
|
||||||
status?: SqlQueryStatus
|
|
||||||
category?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetSqlStoredProceduresInput extends PagedAndSortedResultRequestDto {
|
|
||||||
filter?: string
|
|
||||||
dataSourceCode?: string
|
|
||||||
status?: SqlQueryStatus
|
|
||||||
category?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetSqlViewsInput extends PagedAndSortedResultRequestDto {
|
|
||||||
filter?: string
|
|
||||||
dataSourceCode?: string
|
|
||||||
status?: SqlQueryStatus
|
|
||||||
category?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database Metadata DTOs
|
|
||||||
export interface DatabaseTableDto {
|
export interface DatabaseTableDto {
|
||||||
schemaName: string
|
schemaName: string
|
||||||
tableName: string
|
tableName: string
|
||||||
fullName: string
|
fullName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SqlNativeObjectDto {
|
||||||
|
schemaName: string
|
||||||
|
objectName: string
|
||||||
|
fullName: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface DatabaseColumnDto {
|
export interface DatabaseColumnDto {
|
||||||
columnName: string
|
columnName: string
|
||||||
dataType: string
|
dataType: string
|
||||||
|
|
@ -262,12 +43,11 @@ export interface DatabaseColumnDto {
|
||||||
maxLength?: number
|
maxLength?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unified Object Explorer Response
|
// Object Explorer Response — mirrors live SQL Server catalog
|
||||||
export interface SqlObjectExplorerDto {
|
export interface SqlObjectExplorerDto {
|
||||||
queries: SqlQueryDto[]
|
|
||||||
storedProcedures: SqlStoredProcedureDto[]
|
|
||||||
views: SqlViewDto[]
|
|
||||||
functions: SqlFunctionDto[]
|
|
||||||
tables: DatabaseTableDto[]
|
tables: DatabaseTableDto[]
|
||||||
|
views: SqlNativeObjectDto[]
|
||||||
|
storedProcedures: SqlNativeObjectDto[]
|
||||||
|
functions: SqlNativeObjectDto[]
|
||||||
templates: SqlTemplateDto[]
|
templates: SqlTemplateDto[]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,14 @@
|
||||||
import apiService, { Config } from '@/services/api.service'
|
import apiService, { Config } from '@/services/api.service'
|
||||||
import type {
|
import type {
|
||||||
SqlFunctionDto,
|
|
||||||
UpdateSqlFunctionDto,
|
|
||||||
SqlQueryDto,
|
|
||||||
UpdateSqlQueryDto,
|
|
||||||
CreateSqlQueryDto,
|
|
||||||
ExecuteSqlQueryDto,
|
ExecuteSqlQueryDto,
|
||||||
SqlStoredProcedureDto,
|
|
||||||
UpdateSqlStoredProcedureDto,
|
|
||||||
DeployStoredProcedureDto,
|
|
||||||
SqlViewDto,
|
|
||||||
UpdateSqlViewDto,
|
|
||||||
DeployViewDto,
|
|
||||||
DeployFunctionDto,
|
|
||||||
SqlQueryExecutionResultDto,
|
SqlQueryExecutionResultDto,
|
||||||
DatabaseColumnDto,
|
DatabaseColumnDto,
|
||||||
DatabaseTableDto,
|
|
||||||
SqlObjectExplorerDto,
|
SqlObjectExplorerDto,
|
||||||
} from '@/proxy/sql-query-manager/models'
|
} from '@/proxy/sql-query-manager/models'
|
||||||
|
|
||||||
export class SqlObjectManagerService {
|
export class SqlObjectManagerService {
|
||||||
apiName = 'Default'
|
apiName = 'Default'
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all SQL objects for Object Explorer in a single call
|
|
||||||
*/
|
|
||||||
getAllObjects = (dataSourceCode: string, config?: Partial<Config>) =>
|
getAllObjects = (dataSourceCode: string, config?: Partial<Config>) =>
|
||||||
apiService.fetchData<SqlObjectExplorerDto, void>(
|
apiService.fetchData<SqlObjectExplorerDto, void>(
|
||||||
{
|
{
|
||||||
|
|
@ -35,36 +19,6 @@ export class SqlObjectManagerService {
|
||||||
{ apiName: this.apiName, ...config },
|
{ apiName: this.apiName, ...config },
|
||||||
)
|
)
|
||||||
|
|
||||||
// Query Operations
|
|
||||||
createQuery = (input: CreateSqlQueryDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlQueryDto, CreateSqlQueryDto>(
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
url: '/api/app/sql-object-manager/query',
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
updateQuery = (id: string, input: UpdateSqlQueryDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlQueryDto, UpdateSqlQueryDto>(
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
url: `/api/app/sql-object-manager/query/${id}`,
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deleteQuery = (id: string, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<void, void>(
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
url: `/api/app/sql-object-manager/${id}/query`,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
executeQuery = (input: ExecuteSqlQueryDto, config?: Partial<Config>) =>
|
executeQuery = (input: ExecuteSqlQueryDto, config?: Partial<Config>) =>
|
||||||
apiService.fetchData<SqlQueryExecutionResultDto, ExecuteSqlQueryDto>(
|
apiService.fetchData<SqlQueryExecutionResultDto, ExecuteSqlQueryDto>(
|
||||||
{
|
{
|
||||||
|
|
@ -75,106 +29,6 @@ export class SqlObjectManagerService {
|
||||||
{ apiName: this.apiName, ...config },
|
{ apiName: this.apiName, ...config },
|
||||||
)
|
)
|
||||||
|
|
||||||
executeSavedQuery = (id: string, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlQueryExecutionResultDto, void>(
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
url: `/api/app/sql-object-manager/execute-saved-query/${id}`,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
// Stored Procedure Operations
|
|
||||||
updateStoredProcedure = (id: string, input: UpdateSqlStoredProcedureDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlStoredProcedureDto, UpdateSqlStoredProcedureDto>(
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
url: `/api/app/sql-object-manager/stored-procedure/${id}`,
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deleteStoredProcedure = (id: string, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<void, void>(
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
url: `/api/app/sql-object-manager/${id}/stored-procedure`,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deployStoredProcedure = (input: DeployStoredProcedureDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlQueryExecutionResultDto, DeployStoredProcedureDto>(
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
url: '/api/app/sql-object-manager/deploy-stored-procedure',
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
// View Operations
|
|
||||||
updateView = (id: string, input: UpdateSqlViewDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlViewDto, UpdateSqlViewDto>(
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
url: `/api/app/sql-object-manager/view/${id}`,
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deleteView = (id: string, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<void, void>(
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
url: `/api/app/sql-object-manager/${id}/view`,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deployView = (input: DeployViewDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlQueryExecutionResultDto, DeployViewDto>(
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
url: '/api/app/sql-object-manager/deploy-view',
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
// Function Operations
|
|
||||||
updateFunction = (id: string, input: UpdateSqlFunctionDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlFunctionDto, UpdateSqlFunctionDto>(
|
|
||||||
{
|
|
||||||
method: 'PUT',
|
|
||||||
url: `/api/app/sql-object-manager/function/${id}`,
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deleteFunction = (id: string, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<void, void>(
|
|
||||||
{
|
|
||||||
method: 'DELETE',
|
|
||||||
url: `/api/app/sql-object-manager/${id}/function`,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
deployFunction = (input: DeployFunctionDto, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<SqlQueryExecutionResultDto, DeployFunctionDto>(
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
url: '/api/app/sql-object-manager/deploy-function',
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
|
|
||||||
// Database Metadata Operations
|
|
||||||
getTableColumns = (dataSourceCode: string, schemaName: string, tableName: string, config?: Partial<Config>) =>
|
getTableColumns = (dataSourceCode: string, schemaName: string, tableName: string, config?: Partial<Config>) =>
|
||||||
apiService.fetchData<DatabaseColumnDto[], void>(
|
apiService.fetchData<DatabaseColumnDto[], void>(
|
||||||
{
|
{
|
||||||
|
|
@ -194,18 +48,6 @@ export class SqlObjectManagerService {
|
||||||
},
|
},
|
||||||
{ apiName: this.apiName, ...config },
|
{ apiName: this.apiName, ...config },
|
||||||
)
|
)
|
||||||
|
|
||||||
// Smart Save - Analyzes SQL and saves to appropriate table with auto-deploy
|
|
||||||
smartSave = (input: { sqlText: string; dataSourceCode: string; name?: string; description?: string }, config?: Partial<Config>) =>
|
|
||||||
apiService.fetchData<{ objectType: string; objectId: string; deployed: boolean; message: string }, typeof input>(
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
url: '/api/app/sql-object-manager/smart-save',
|
|
||||||
data: input,
|
|
||||||
},
|
|
||||||
{ apiName: this.apiName, ...config },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export service instance
|
|
||||||
export const sqlObjectManagerService = new SqlObjectManagerService()
|
export const sqlObjectManagerService = new SqlObjectManagerService()
|
||||||
|
|
|
||||||
|
|
@ -1,454 +1,244 @@
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Dialog, Button, Notification, toast } from '@/components/ui'
|
|
||||||
import {
|
import {
|
||||||
FaRegFolder,
|
FaRegFolder,
|
||||||
FaRegFolderOpen,
|
FaRegFolderOpen,
|
||||||
FaRegFileAlt,
|
|
||||||
FaCog,
|
|
||||||
FaColumns,
|
FaColumns,
|
||||||
FaCode,
|
|
||||||
FaSyncAlt,
|
FaSyncAlt,
|
||||||
FaEdit,
|
|
||||||
FaTrash,
|
|
||||||
FaTable,
|
FaTable,
|
||||||
FaPlus,
|
FaPlus,
|
||||||
|
FaEye,
|
||||||
|
FaCog,
|
||||||
|
FaCode,
|
||||||
|
FaDatabase,
|
||||||
|
FaTrash,
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import type {
|
import type { DatabaseTableDto, SqlNativeObjectDto } from '@/proxy/sql-query-manager/models'
|
||||||
SqlFunctionDto,
|
|
||||||
SqlQueryDto,
|
|
||||||
SqlStoredProcedureDto,
|
|
||||||
SqlViewDto,
|
|
||||||
SqlObjectType,
|
|
||||||
} from '@/proxy/sql-query-manager/models'
|
|
||||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
export type SqlObject = SqlFunctionDto | SqlQueryDto | SqlStoredProcedureDto | SqlViewDto
|
type FolderKey = 'tables' | 'views' | 'procedures' | 'functions'
|
||||||
|
|
||||||
interface TreeNode {
|
interface TreeNode {
|
||||||
id: string
|
id: string
|
||||||
label: string
|
label: string
|
||||||
type: 'root' | 'folder' | 'object' | 'column'
|
type: 'root' | 'folder' | 'object'
|
||||||
objectType?: SqlObjectType
|
folder?: FolderKey
|
||||||
data?: SqlObject | any
|
data?: DatabaseTableDto | SqlNativeObjectDto
|
||||||
children?: TreeNode[]
|
children?: TreeNode[]
|
||||||
expanded?: boolean
|
|
||||||
isColumn?: boolean
|
|
||||||
parentTable?: { schemaName: string; tableName: string }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SqlObjectExplorerProps {
|
interface SqlObjectExplorerProps {
|
||||||
dataSource: string | null
|
dataSource: string | null
|
||||||
onObjectSelect: (object: SqlObject | null, objectType: SqlObjectType | null) => void
|
|
||||||
selectedObject: SqlObject | null
|
|
||||||
onTemplateSelect?: (template: string, templateType: string) => void
|
onTemplateSelect?: (template: string, templateType: string) => void
|
||||||
onShowTableColumns?: (schemaName: string, tableName: string) => void
|
onViewDefinition?: (schemaName: string, objectName: string) => void
|
||||||
onDesignTable?: (schemaName: string, tableName: string) => void
|
onDesignTable?: (schemaName: string, tableName: string) => void
|
||||||
onNewTable?: () => void
|
onNewTable?: () => void
|
||||||
refreshTrigger?: number
|
refreshTrigger?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FOLDER_META: Record<FolderKey, { label: string; color: string }> = {
|
||||||
|
tables: { label: 'Tables', color: 'text-teal-500' },
|
||||||
|
views: { label: 'Views', color: 'text-purple-500' },
|
||||||
|
procedures: { label: 'Stored Procedures', color: 'text-green-600' },
|
||||||
|
functions: { label: 'Functions', color: 'text-orange-500' },
|
||||||
|
}
|
||||||
|
|
||||||
const SqlObjectExplorer = ({
|
const SqlObjectExplorer = ({
|
||||||
dataSource,
|
dataSource,
|
||||||
onObjectSelect,
|
|
||||||
selectedObject,
|
|
||||||
onTemplateSelect,
|
onTemplateSelect,
|
||||||
onShowTableColumns,
|
onViewDefinition,
|
||||||
onDesignTable,
|
onDesignTable,
|
||||||
onNewTable,
|
onNewTable,
|
||||||
refreshTrigger,
|
refreshTrigger,
|
||||||
}: SqlObjectExplorerProps) => {
|
}: SqlObjectExplorerProps) => {
|
||||||
const { translate } = useLocalization()
|
const { translate } = useLocalization()
|
||||||
const [treeData, setTreeData] = useState<TreeNode[]>([])
|
const [treeData, setTreeData] = useState<TreeNode[]>([])
|
||||||
const [expandedNodes, setExpandedNodes] = useState<Set<string>>(
|
const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set(['root']))
|
||||||
new Set(['root']), // Only root expanded by default
|
|
||||||
)
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [filterText, setFilterText] = useState('')
|
const [filterText, setFilterText] = useState('')
|
||||||
|
const [dropConfirm, setDropConfirm] = useState<{ node: TreeNode } | null>(null)
|
||||||
|
const [dropping, setDropping] = useState(false)
|
||||||
const [contextMenu, setContextMenu] = useState<{
|
const [contextMenu, setContextMenu] = useState<{
|
||||||
show: boolean
|
show: boolean; x: number; y: number; node: TreeNode | null
|
||||||
x: number
|
|
||||||
y: number
|
|
||||||
node: TreeNode | null
|
|
||||||
}>({ show: false, x: 0, y: 0, node: null })
|
}>({ show: false, x: 0, y: 0, node: null })
|
||||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false)
|
|
||||||
const [objectToDelete, setObjectToDelete] = useState<{
|
|
||||||
object: SqlObject
|
|
||||||
type: SqlObjectType
|
|
||||||
} | null>(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dataSource) {
|
if (dataSource) loadObjects()
|
||||||
loadObjects()
|
else setTreeData([])
|
||||||
} else {
|
}, [dataSource, refreshTrigger])
|
||||||
setTreeData([])
|
|
||||||
}
|
|
||||||
}, [dataSource, refreshTrigger]) // refreshTrigger değişince de yenile
|
|
||||||
|
|
||||||
const loadObjects = async () => {
|
const loadObjects = async () => {
|
||||||
if (!dataSource) return
|
if (!dataSource) return
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
// Single API call to get all objects
|
const { data } = await sqlObjectManagerService.getAllObjects(dataSource)
|
||||||
const response = await sqlObjectManagerService.getAllObjects(dataSource || '')
|
|
||||||
const allObjects = response.data
|
|
||||||
|
|
||||||
const tree: TreeNode[] = [
|
const makeObjectNode = (folder: FolderKey, obj: SqlNativeObjectDto): TreeNode => ({
|
||||||
{
|
id: `${folder}-${obj.schemaName}-${obj.objectName}`,
|
||||||
|
label: obj.fullName ?? `[${obj.schemaName}].[${obj.objectName}]`,
|
||||||
|
type: 'object',
|
||||||
|
folder,
|
||||||
|
data: obj,
|
||||||
|
})
|
||||||
|
|
||||||
|
const tree: TreeNode[] = [{
|
||||||
id: 'root',
|
id: 'root',
|
||||||
label: dataSource || 'Database',
|
label: dataSource,
|
||||||
type: 'root',
|
type: 'root',
|
||||||
expanded: true,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: 'tables',
|
id: 'tables',
|
||||||
label: `${translate('::App.Platform.Tables')} (${allObjects.tables.length})`,
|
label: `Tables (${data.tables.length})`,
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
expanded: expandedNodes.has('tables'),
|
folder: 'tables',
|
||||||
children:
|
children: data.tables.map((t) => ({
|
||||||
allObjects.tables.map((t) => ({
|
id: `tables-${t.schemaName}-${t.tableName}`,
|
||||||
id: `table-${t.schemaName}-${t.tableName}`,
|
label: t.fullName ?? `[${t.schemaName}].[${t.tableName}]`,
|
||||||
label: t.fullName,
|
|
||||||
type: 'object' as const,
|
type: 'object' as const,
|
||||||
|
folder: 'tables' as FolderKey,
|
||||||
data: t,
|
data: t,
|
||||||
})) || [],
|
})),
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'procedures',
|
|
||||||
label: `${translate('::App.Platform.StoredProcedures')} (${allObjects.storedProcedures.length})`,
|
|
||||||
type: 'folder',
|
|
||||||
objectType: 2,
|
|
||||||
expanded: expandedNodes.has('procedures'),
|
|
||||||
children:
|
|
||||||
allObjects.storedProcedures.map((p) => {
|
|
||||||
const deployInfo = p.isDeployed && p.lastDeployedAt
|
|
||||||
? ` (${new Date(p.lastDeployedAt).toLocaleString('tr-TR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })})`
|
|
||||||
: '';
|
|
||||||
const customBadge = p.isCustom ? ' 📝' : ' 🗄️';
|
|
||||||
return {
|
|
||||||
id: p.id!,
|
|
||||||
label: `${p.displayName || p.procedureName}${customBadge}${p.isDeployed ? ' ✅' : ' ❌'}${deployInfo}`,
|
|
||||||
type: 'object' as const,
|
|
||||||
objectType: 2 as SqlObjectType,
|
|
||||||
data: p,
|
|
||||||
};
|
|
||||||
}) || [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'views',
|
id: 'views',
|
||||||
label: `${translate('::App.Platform.Views')} (${allObjects.views.length})`,
|
label: `Views (${data.views.length})`,
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
objectType: 3,
|
folder: 'views',
|
||||||
expanded: expandedNodes.has('views'),
|
children: data.views.map((v) => makeObjectNode('views', v)),
|
||||||
children:
|
},
|
||||||
allObjects.views.map((v) => {
|
{
|
||||||
const deployInfo = v.isDeployed && v.lastDeployedAt
|
id: 'procedures',
|
||||||
? ` (${new Date(v.lastDeployedAt).toLocaleString('tr-TR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })})`
|
label: `Stored Procedures (${data.storedProcedures.length})`,
|
||||||
: '';
|
type: 'folder',
|
||||||
const customBadge = v.isCustom ? ' 📝' : ' 🗄️';
|
folder: 'procedures',
|
||||||
return {
|
children: data.storedProcedures.map((p) => makeObjectNode('procedures', p)),
|
||||||
id: v.id!,
|
|
||||||
label: `${v.displayName || v.viewName}${customBadge}${v.isDeployed ? ' ✅' : ' ❌'}${deployInfo}`,
|
|
||||||
type: 'object' as const,
|
|
||||||
objectType: 3 as SqlObjectType,
|
|
||||||
data: v,
|
|
||||||
};
|
|
||||||
}) || [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'functions',
|
id: 'functions',
|
||||||
label: `${translate('::App.Platform.Functions')} (${allObjects.functions.length})`,
|
label: `Functions (${data.functions.length})`,
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
objectType: 4,
|
folder: 'functions',
|
||||||
expanded: expandedNodes.has('functions'),
|
children: data.functions.map((f) => makeObjectNode('functions', f)),
|
||||||
children:
|
|
||||||
allObjects.functions.map((f) => {
|
|
||||||
const deployInfo = f.isDeployed && f.lastDeployedAt
|
|
||||||
? ` (${new Date(f.lastDeployedAt).toLocaleString('tr-TR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })})`
|
|
||||||
: '';
|
|
||||||
const customBadge = f.isCustom ? ' 📝' : ' 🗄️';
|
|
||||||
return {
|
|
||||||
id: f.id!,
|
|
||||||
label: `${f.displayName || f.functionName}${customBadge}${f.isDeployed ? ' ✅' : ' ❌'}${deployInfo}`,
|
|
||||||
type: 'object' as const,
|
|
||||||
objectType: 4 as SqlObjectType,
|
|
||||||
data: f,
|
|
||||||
};
|
|
||||||
}) || [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'queries',
|
|
||||||
label: `${translate('::App.Platform.Queries')} (${allObjects.queries.length})`,
|
|
||||||
type: 'folder',
|
|
||||||
objectType: 1,
|
|
||||||
expanded: expandedNodes.has('queries'),
|
|
||||||
children:
|
|
||||||
allObjects.queries.map((q) => ({
|
|
||||||
id: q.id || '',
|
|
||||||
label: q.name,
|
|
||||||
type: 'object' as const,
|
|
||||||
objectType: 1 as SqlObjectType,
|
|
||||||
data: q,
|
|
||||||
})) || [],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
}]
|
||||||
]
|
|
||||||
|
|
||||||
setTreeData(tree)
|
setTreeData(tree)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.push(
|
console.error('Failed to load objects', error)
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{error.response?.data?.error?.message || translate('::App.Platform.FailedToLoadObjects')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadTableColumns = async (schemaName: string, tableName: string): Promise<TreeNode[]> => {
|
const toggleNode = (nodeId: string) => {
|
||||||
try {
|
setExpandedNodes((prev) => {
|
||||||
const response = await sqlObjectManagerService.getTableColumns(
|
const next = new Set(prev)
|
||||||
dataSource || '',
|
next.has(nodeId) ? next.delete(nodeId) : next.add(nodeId)
|
||||||
schemaName,
|
return next
|
||||||
tableName,
|
|
||||||
)
|
|
||||||
return response.data.map((col) => ({
|
|
||||||
id: `column-${schemaName}-${tableName}-${col.columnName}`,
|
|
||||||
label: `${col.columnName} (${col.dataType}${col.maxLength ? `(${col.maxLength})` : ''})${col.isNullable ? '' : ' NOT NULL'}`,
|
|
||||||
type: 'column' as const,
|
|
||||||
isColumn: true,
|
|
||||||
data: col,
|
|
||||||
parentTable: { schemaName, tableName },
|
|
||||||
}))
|
|
||||||
} catch (error) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toggleNode = async (nodeId: string) => {
|
|
||||||
const newSet = new Set(expandedNodes)
|
|
||||||
|
|
||||||
if (newSet.has(nodeId)) {
|
|
||||||
newSet.delete(nodeId)
|
|
||||||
setExpandedNodes(newSet)
|
|
||||||
} else {
|
|
||||||
newSet.add(nodeId)
|
|
||||||
setExpandedNodes(newSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const findNodeById = (nodes: TreeNode[], id: string): TreeNode | null => {
|
|
||||||
for (const node of nodes) {
|
|
||||||
if (node.id === id) return node
|
|
||||||
if (node.children) {
|
|
||||||
const found = findNodeById(node.children, id)
|
|
||||||
if (found) return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateNodeChildren = (
|
|
||||||
nodes: TreeNode[],
|
|
||||||
nodeId: string,
|
|
||||||
children: TreeNode[],
|
|
||||||
): TreeNode[] => {
|
|
||||||
return nodes.map((node) => {
|
|
||||||
if (node.id === nodeId) {
|
|
||||||
return { ...node, children }
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
return { ...node, children: updateNodeChildren(node.children, nodeId, children) }
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterTree = (nodes: TreeNode[], searchText: string): TreeNode[] => {
|
const filterTree = (nodes: TreeNode[], search: string): TreeNode[] => {
|
||||||
if (!searchText.trim()) return nodes
|
if (!search.trim()) return nodes
|
||||||
|
const q = search.toLowerCase()
|
||||||
const search = searchText.toLowerCase()
|
return nodes
|
||||||
const filtered = nodes
|
|
||||||
.map((node) => {
|
.map((node) => {
|
||||||
const matchesSearch = node.label.toLowerCase().includes(search)
|
const match = node.label.toLowerCase().includes(q)
|
||||||
const filteredChildren = node.children ? filterTree(node.children, searchText) : []
|
const kids = node.children ? filterTree(node.children, search) : []
|
||||||
|
if (match || kids.length > 0)
|
||||||
if (matchesSearch || filteredChildren.length > 0) {
|
return { ...node, children: kids.length > 0 ? kids : node.children } as TreeNode
|
||||||
return {
|
|
||||||
...node,
|
|
||||||
children: filteredChildren.length > 0 ? filteredChildren : node.children,
|
|
||||||
} as TreeNode
|
|
||||||
}
|
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
.filter((node) => node !== null) as TreeNode[]
|
.filter(Boolean) as TreeNode[]
|
||||||
|
|
||||||
return filtered
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleNodeClick = (node: TreeNode) => {
|
const handleNodeClick = (node: TreeNode) => {
|
||||||
if (node.type === 'folder' || node.type === 'root') {
|
if (node.type !== 'object') { toggleNode(node.id); return }
|
||||||
toggleNode(node.id)
|
|
||||||
} else if (node.type === 'column') {
|
if (node.folder === 'tables') {
|
||||||
// Column clicked - do nothing or show info
|
// Generate SELECT template for tables
|
||||||
return
|
const t = node.data as DatabaseTableDto
|
||||||
} else if (node.type === 'object' && node.data) {
|
onTemplateSelect?.(`SELECT TOP 10 *\nFROM ${t.fullName ?? `[${t.schemaName}].[${t.tableName}]`};`, 'table-select')
|
||||||
// Check if it's a table - generate SELECT template
|
} else {
|
||||||
if (node.id.startsWith('table-') && onTemplateSelect) {
|
// Load native object definition into editor
|
||||||
const table = node.data as any
|
const obj = node.data as SqlNativeObjectDto
|
||||||
const selectQuery = `SELECT TOP 10 * \nFROM ${table.fullName || `[${table.schemaName}].[${table.tableName}]`};`
|
onViewDefinition?.(obj.schemaName, obj.objectName)
|
||||||
onTemplateSelect(selectQuery, 'table-select')
|
|
||||||
} else if (node.objectType) {
|
|
||||||
onObjectSelect(node.data, node.objectType)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleContextMenu = (e: React.MouseEvent, node: TreeNode) => {
|
const buildDropSql = (node: TreeNode): string => {
|
||||||
e.preventDefault()
|
if (node.folder === 'tables') {
|
||||||
|
const t = node.data as DatabaseTableDto
|
||||||
// Don't show context menu for columns
|
return `DROP TABLE ${t.fullName ?? `[${t.schemaName}].[${t.tableName}]`};`
|
||||||
if (node.type === 'column') {
|
}
|
||||||
return
|
const obj = node.data as SqlNativeObjectDto
|
||||||
|
const keyword =
|
||||||
|
node.folder === 'views' ? 'VIEW' :
|
||||||
|
node.folder === 'procedures' ? 'PROCEDURE' :
|
||||||
|
'FUNCTION'
|
||||||
|
return `DROP ${keyword} ${obj.fullName ?? `[${obj.schemaName}].[${obj.objectName}]`};`
|
||||||
}
|
}
|
||||||
|
|
||||||
setContextMenu({
|
const handleDrop = async () => {
|
||||||
show: true,
|
if (!dropConfirm || !dataSource) return
|
||||||
x: e.clientX,
|
setDropping(true)
|
||||||
y: e.clientY,
|
|
||||||
node,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDelete = async () => {
|
|
||||||
if (!objectToDelete || !objectToDelete.object.id) return
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { object, type } = objectToDelete
|
await sqlObjectManagerService.executeQuery({
|
||||||
|
queryText: buildDropSql(dropConfirm.node),
|
||||||
switch (type) {
|
dataSourceCode: dataSource,
|
||||||
case 1:
|
})
|
||||||
await sqlObjectManagerService.deleteQuery(object.id!)
|
setDropConfirm(null)
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
await sqlObjectManagerService.deleteStoredProcedure(object.id!)
|
|
||||||
break
|
|
||||||
case 3:
|
|
||||||
await sqlObjectManagerService.deleteView(object.id!)
|
|
||||||
break
|
|
||||||
case 4:
|
|
||||||
await sqlObjectManagerService.deleteFunction(object.id!)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.push(
|
|
||||||
<Notification type="success" title={translate('::App.Platform.Success')}>
|
|
||||||
{translate('::App.Platform.ObjectDeletedSuccessfully')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
|
|
||||||
setShowDeleteDialog(false)
|
|
||||||
setObjectToDelete(null)
|
|
||||||
loadObjects()
|
loadObjects()
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('Drop failed', err)
|
||||||
|
} finally {
|
||||||
|
setDropping(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedObject?.id === object.id) {
|
const closeCtx = () => setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||||
onObjectSelect(null, null)
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{error.response?.data?.error?.message || translate('::App.Platform.FailedToDeleteObject')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getIcon = (node: TreeNode) => {
|
const getIcon = (node: TreeNode) => {
|
||||||
if (node.type === 'root') return <FaRegFolder className="text-blue-500" />
|
if (node.type === 'root') return <FaDatabase className="text-blue-500" />
|
||||||
|
|
||||||
if (node.type === 'folder') {
|
if (node.type === 'folder') {
|
||||||
const isExpanded = expandedNodes.has(node.id)
|
const open = expandedNodes.has(node.id)
|
||||||
|
const cls = FOLDER_META[node.folder!]?.color ?? 'text-blue-500'
|
||||||
// Tables folder
|
return open
|
||||||
if (node.id === 'tables')
|
? <FaRegFolderOpen className={cls} />
|
||||||
return isExpanded ? (
|
: <FaRegFolder className={cls} />
|
||||||
<FaRegFolderOpen className="text-blue-500" />
|
|
||||||
) : (
|
|
||||||
<FaRegFolder className="text-blue-500" />
|
|
||||||
)
|
|
||||||
|
|
||||||
if (node.objectType === 1)
|
|
||||||
return isExpanded ? (
|
|
||||||
<FaRegFolderOpen className="text-yellow-500" />
|
|
||||||
) : (
|
|
||||||
<FaRegFolder className="text-yellow-500" />
|
|
||||||
)
|
|
||||||
|
|
||||||
if (node.objectType === 2)
|
|
||||||
return isExpanded ? (
|
|
||||||
<FaRegFolderOpen className="text-green-500" />
|
|
||||||
) : (
|
|
||||||
<FaRegFolder className="text-green-500" />
|
|
||||||
)
|
|
||||||
|
|
||||||
if (node.objectType === 3)
|
|
||||||
return isExpanded ? (
|
|
||||||
<FaRegFolderOpen className="text-purple-500" />
|
|
||||||
) : (
|
|
||||||
<FaRegFolder className="text-purple-500" />
|
|
||||||
)
|
|
||||||
|
|
||||||
if (node.objectType === 4)
|
|
||||||
return isExpanded ? (
|
|
||||||
<FaRegFolderOpen className="text-red-500" />
|
|
||||||
) : (
|
|
||||||
<FaRegFolder className="text-red-500" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
if (node.folder === 'tables') return <FaTable className="text-teal-500" />
|
||||||
if (node.type === 'object') {
|
if (node.folder === 'views') return <FaEye className="text-purple-500" />
|
||||||
if (node.objectType === 1) return <FaRegFileAlt className="text-gray-500" />
|
if (node.folder === 'procedures') return <FaCog className="text-green-600" />
|
||||||
if (node.objectType === 2) return <FaCog className="text-gray-500" />
|
if (node.folder === 'functions') return <FaCode className="text-orange-500" />
|
||||||
if (node.objectType === 3) return <FaColumns className="text-gray-500" />
|
return <FaColumns className="text-gray-400" />
|
||||||
if (node.objectType === 4) return <FaCode className="text-gray-500" />
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.type === 'column') {
|
|
||||||
return <FaColumns className="text-gray-400 text-sm" />
|
|
||||||
}
|
|
||||||
|
|
||||||
return <FaRegFolder />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderNode = (node: TreeNode, level = 0) => {
|
const renderNode = (node: TreeNode, level = 0) => {
|
||||||
const isExpanded = expandedNodes.has(node.id)
|
const isExpanded = expandedNodes.has(node.id)
|
||||||
const isSelected = node.type === 'object' && selectedObject?.id === node.id
|
|
||||||
const isColumn = node.type === 'column'
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={node.id}>
|
<div key={node.id}>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center gap-2 py-1 px-2 ${isColumn ? 'cursor-default' : 'cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700'} rounded ${
|
className="group flex items-center gap-2 py-1 px-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
|
||||||
isSelected ? 'bg-blue-100 dark:bg-blue-900' : ''
|
|
||||||
}`}
|
|
||||||
style={{ paddingLeft: `${level * 16 + 8}px` }}
|
style={{ paddingLeft: `${level * 16 + 8}px` }}
|
||||||
onClick={() => !isColumn && handleNodeClick(node)}
|
onClick={() => handleNodeClick(node)}
|
||||||
onContextMenu={(e) => !isColumn && handleContextMenu(e, node)}
|
onContextMenu={(e) => { e.preventDefault(); setContextMenu({ show: true, x: e.clientX, y: e.clientY, node }) }}
|
||||||
>
|
>
|
||||||
{getIcon(node)}
|
{getIcon(node)}
|
||||||
<span className={`text-sm flex-1 ${isColumn ? 'text-gray-600 dark:text-gray-400' : ''}`}>
|
<span className="text-sm flex-1 truncate">{node.label}</span>
|
||||||
{node.label}
|
{node.type === 'object' && (
|
||||||
</span>
|
<button
|
||||||
|
title="Drop"
|
||||||
|
className="opacity-0 group-hover:opacity-100 p-1 rounded hover:bg-red-100 dark:hover:bg-red-900 text-red-500 transition-opacity flex-shrink-0"
|
||||||
|
onClick={(e) => { e.stopPropagation(); setDropConfirm({ node }) }}
|
||||||
|
>
|
||||||
|
<FaTrash className="text-xs" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isExpanded && node.children && (
|
{isExpanded && node.children && (
|
||||||
<div>{node.children.map((child) => renderNode(child, level + 1))}</div>
|
<div>{node.children.map((c) => renderNode(c, level + 1))}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
@ -456,11 +246,20 @@ const SqlObjectExplorer = ({
|
||||||
|
|
||||||
const filteredTree = filterTree(treeData, filterText)
|
const filteredTree = filterTree(treeData, filterText)
|
||||||
|
|
||||||
|
// Context menu items per folder
|
||||||
|
const ctxNode = contextMenu.node
|
||||||
|
const isTableObj = ctxNode?.type === 'object' && ctxNode.folder === 'tables'
|
||||||
|
const isNativeObj = ctxNode?.type === 'object' && ctxNode.folder !== 'tables'
|
||||||
|
const isTablesDir = ctxNode?.id === 'tables'
|
||||||
|
const isViewsDir = ctxNode?.id === 'views'
|
||||||
|
const isProcsDir = ctxNode?.id === 'procedures'
|
||||||
|
const isFuncsDir = ctxNode?.id === 'functions'
|
||||||
|
const isFolderNode = ctxNode?.type === 'folder'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col">
|
<div className="flex-1 flex flex-col min-h-0">
|
||||||
{/* Filter and Refresh Controls */}
|
{/* Search + refresh */}
|
||||||
<div className="p-2 border-b space-y-2 flex-shrink-0">
|
<div className="p-2 border-b flex gap-2 flex-shrink-0">
|
||||||
<div className="flex gap-2">
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={translate('::App.Platform.Search')}
|
placeholder={translate('::App.Platform.Search')}
|
||||||
|
|
@ -477,183 +276,89 @@ const SqlObjectExplorer = ({
|
||||||
<FaSyncAlt className={loading ? 'animate-spin' : ''} />
|
<FaSyncAlt className={loading ? 'animate-spin' : ''} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Tree */}
|
||||||
|
<div className="flex-1 overflow-auto">
|
||||||
|
{loading && <div className="text-center py-8 text-gray-500 text-sm">{translate('::App.Platform.Loading')}</div>}
|
||||||
|
{!loading && treeData.length === 0 && <div className="text-center py-8 text-gray-500 text-sm">{translate('::App.Platform.NoDataSourceSelected')}</div>}
|
||||||
|
{!loading && filteredTree.length > 0 && <div className="p-1">{filteredTree.map((n) => renderNode(n))}</div>}
|
||||||
|
{!loading && treeData.length > 0 && filteredTree.length === 0 && <div className="text-center py-8 text-gray-500 text-sm">{translate('::App.Platform.NoResultsFound')}</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tree Content */}
|
{/* Context menu */}
|
||||||
<div className="h-[calc(100vh-265px)] overflow-auto">
|
|
||||||
{loading && (
|
|
||||||
<div className="text-center py-8 text-gray-500">
|
|
||||||
{translate('::App.Platform.Loading')}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!loading && treeData.length === 0 && (
|
|
||||||
<div className="text-center py-8 text-gray-500">
|
|
||||||
{translate('::App.Platform.NoDataSourceSelected')}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!loading && filteredTree.length > 0 && (
|
|
||||||
<div className="space-y-1 p-2">{filteredTree.map((node) => renderNode(node))}</div>
|
|
||||||
)}
|
|
||||||
{!loading && treeData.length > 0 && filteredTree.length === 0 && (
|
|
||||||
<div className="text-center py-8 text-gray-500">
|
|
||||||
{translate('::App.Platform.NoResultsFound')}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{contextMenu.show && (
|
{contextMenu.show && (
|
||||||
<>
|
<>
|
||||||
|
<div className="fixed inset-0 z-40" onClick={closeCtx} />
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-40"
|
className="fixed z-50 bg-white dark:bg-gray-800 shadow-lg rounded border border-gray-200 dark:border-gray-700 py-1 min-w-[180px]"
|
||||||
onClick={() => setContextMenu({ show: false, x: 0, y: 0, node: null })}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="fixed z-50 bg-white dark:bg-gray-800 shadow-lg rounded border border-gray-200 dark:border-gray-700 py-1"
|
|
||||||
style={{ top: contextMenu.y, left: contextMenu.x }}
|
style={{ top: contextMenu.y, left: contextMenu.x }}
|
||||||
>
|
>
|
||||||
{contextMenu.node?.id?.startsWith('table-') && (
|
{/* TABLE object <20> Design */}
|
||||||
<button
|
{isTableObj && (
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const tableData = contextMenu.node?.data as any
|
const t = ctxNode!.data as DatabaseTableDto
|
||||||
if (tableData && onDesignTable) {
|
onDesignTable?.(t.schemaName, t.tableName)
|
||||||
onDesignTable(tableData.schemaName, tableData.tableName)
|
closeCtx()
|
||||||
}
|
}}>
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
<FaTable className="text-teal-600" /> Design Table
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaTable className="inline mr-2 text-teal-600" />
|
|
||||||
Design
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{contextMenu.node?.type === 'object' && contextMenu.node?.objectType && contextMenu.node?.data?.isCustom && (
|
{/* NATIVE object <20> View Definition */}
|
||||||
<>
|
{isNativeObj && (
|
||||||
<button
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (contextMenu.node?.data && contextMenu.node?.objectType) {
|
const obj = ctxNode!.data as SqlNativeObjectDto
|
||||||
onObjectSelect(contextMenu.node.data, contextMenu.node.objectType)
|
onViewDefinition?.(obj.schemaName, obj.objectName)
|
||||||
}
|
closeCtx()
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
}}>
|
||||||
}}
|
{ctxNode!.folder === 'views' && <FaEye className="text-purple-500" />}
|
||||||
>
|
{ctxNode!.folder === 'procedures' && <FaCog className="text-green-600" />}
|
||||||
<FaEdit className="inline mr-2" />
|
{ctxNode!.folder === 'functions' && <FaCode className="text-orange-500" />}
|
||||||
{translate('::App.Platform.Edit')}
|
View Definition
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
{/* FOLDER <20> New ... */}
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm text-red-600"
|
{isTablesDir && (
|
||||||
onClick={() => {
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
if (contextMenu.node?.data && contextMenu.node?.objectType) {
|
onClick={() => { onNewTable?.(); closeCtx() }}>
|
||||||
setObjectToDelete({
|
<FaPlus className="text-teal-600" /> New Table
|
||||||
object: contextMenu.node.data,
|
</button>
|
||||||
type: contextMenu.node.objectType,
|
)}
|
||||||
})
|
{isViewsDir && (
|
||||||
setShowDeleteDialog(true)
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
}
|
onClick={() => { onTemplateSelect?.('', 'create-view'); closeCtx() }}>
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
<FaPlus className="text-purple-500" /> New View
|
||||||
}}
|
</button>
|
||||||
>
|
)}
|
||||||
<FaTrash className="inline mr-2" />
|
{isProcsDir && (
|
||||||
{translate('::App.Platform.Delete')}
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
|
onClick={() => { onTemplateSelect?.('', 'create-procedure'); closeCtx() }}>
|
||||||
|
<FaPlus className="text-green-600" /> New Stored Procedure
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{isFuncsDir && (
|
||||||
|
<>
|
||||||
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
|
onClick={() => { onTemplateSelect?.('', 'create-scalar-function'); closeCtx() }}>
|
||||||
|
<FaPlus className="text-orange-500" /> New Scalar Function
|
||||||
|
</button>
|
||||||
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
|
onClick={() => { onTemplateSelect?.('', 'create-table-function'); closeCtx() }}>
|
||||||
|
<FaPlus className="text-orange-500" /> New Table-Valued Function
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{contextMenu.node?.type === 'object' && contextMenu.node?.objectType && !contextMenu.node?.data?.isCustom && (
|
{/* Separator + Refresh for folders */}
|
||||||
<div className="px-4 py-2 text-xs text-gray-500 italic">
|
{isFolderNode && (
|
||||||
{translate('::App.Platform.NativeObjectViewOnly')}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{contextMenu.node?.type === 'folder' && (
|
|
||||||
<>
|
<>
|
||||||
{/* Tables folder */}
|
|
||||||
{contextMenu.node.id === 'tables' && (
|
|
||||||
<button
|
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
onNewTable?.()
|
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaPlus className="inline mr-2 text-teal-600" />
|
|
||||||
New Table
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Stored Procedures folder */}
|
|
||||||
{contextMenu.node.id === 'procedures' && (
|
|
||||||
<button
|
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
onTemplateSelect?.('', 'create-procedure')
|
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaPlus className="inline mr-2 text-green-600" />
|
|
||||||
New Stored Procedure
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Views folder */}
|
|
||||||
{contextMenu.node.id === 'views' && (
|
|
||||||
<button
|
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
onTemplateSelect?.('', 'create-view')
|
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaPlus className="inline mr-2 text-purple-600" />
|
|
||||||
New View
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Functions folder */}
|
|
||||||
{contextMenu.node.id === 'functions' && (
|
|
||||||
<button
|
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
onTemplateSelect?.('', 'create-scalar-function')
|
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaPlus className="inline mr-2 text-red-500" />
|
|
||||||
New Function
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Queries folder */}
|
|
||||||
{contextMenu.node.id === 'queries' && (
|
|
||||||
<button
|
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
onTemplateSelect?.('', 'select')
|
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaPlus className="inline mr-2 text-yellow-600" />
|
|
||||||
New Query
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Separator */}
|
|
||||||
{contextMenu.node.id !== 'root' && (
|
|
||||||
<div className="my-1 border-t border-gray-100 dark:border-gray-700" />
|
<div className="my-1 border-t border-gray-100 dark:border-gray-700" />
|
||||||
)}
|
<button className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm flex items-center gap-2"
|
||||||
|
onClick={() => { loadObjects(); closeCtx() }}>
|
||||||
{/* Refresh — all folders */}
|
<FaSyncAlt /> {translate('::App.Platform.Refresh')}
|
||||||
<button
|
|
||||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
|
||||||
onClick={() => {
|
|
||||||
loadObjects()
|
|
||||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaSyncAlt className="inline mr-2" />
|
|
||||||
{translate('::App.Platform.Refresh')}
|
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
@ -661,22 +366,42 @@ const SqlObjectExplorer = ({
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Dialog
|
{/* Drop Confirm Dialog */}
|
||||||
isOpen={showDeleteDialog}
|
{dropConfirm && (
|
||||||
onClose={() => setShowDeleteDialog(false)}
|
<>
|
||||||
onRequestClose={() => setShowDeleteDialog(false)}
|
<div className="fixed inset-0 z-50 bg-black/40 flex items-center justify-center" onClick={() => !dropping && setDropConfirm(null)}>
|
||||||
>
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 max-w-sm w-full mx-4" onClick={(e) => e.stopPropagation()}>
|
||||||
<h5 className="mb-4">{translate('::App.Platform.ConfirmDelete')}</h5>
|
<div className="flex items-center gap-3 mb-3">
|
||||||
<p className="mb-4">{translate('::App.Platform.DeleteConfirmationMessage')}</p>
|
<FaTrash className="text-red-500 text-lg flex-shrink-0" />
|
||||||
<div className="flex justify-end gap-2">
|
<h6 className="font-semibold text-gray-900 dark:text-gray-100">Drop Object</h6>
|
||||||
<Button variant="plain" onClick={() => setShowDeleteDialog(false)}>
|
|
||||||
{translate('::Cancel')}
|
|
||||||
</Button>
|
|
||||||
<Button variant="solid" onClick={handleDelete}>
|
|
||||||
{translate('::App.Platform.DeleteAction')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
<p className="text-sm text-gray-600 dark:text-gray-400 mb-1">
|
||||||
|
The following object will be permanently dropped:
|
||||||
|
</p>
|
||||||
|
<code className="block text-sm bg-gray-100 dark:bg-gray-700 rounded px-3 py-2 mb-4 break-all">
|
||||||
|
{buildDropSql(dropConfirm.node)}
|
||||||
|
</code>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<button
|
||||||
|
disabled={dropping}
|
||||||
|
className="px-4 py-1.5 text-sm rounded border hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50"
|
||||||
|
onClick={() => setDropConfirm(null)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
disabled={dropping}
|
||||||
|
className="px-4 py-1.5 text-sm rounded bg-red-600 text-white hover:bg-red-700 disabled:opacity-50 flex items-center gap-2"
|
||||||
|
onClick={handleDrop}
|
||||||
|
>
|
||||||
|
{dropping && <FaSyncAlt className="animate-spin text-xs" />}
|
||||||
|
Drop
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,212 +1,21 @@
|
||||||
import type {
|
interface SqlObjectPropertiesProps {
|
||||||
SqlFunctionDto,
|
object?: any
|
||||||
SqlQueryDto,
|
|
||||||
SqlStoredProcedureDto,
|
|
||||||
SqlViewDto,
|
|
||||||
SqlObjectType,
|
|
||||||
} from '@/proxy/sql-query-manager/models'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
|
|
||||||
export type SqlObject = SqlFunctionDto | SqlQueryDto | SqlStoredProcedureDto | SqlViewDto
|
|
||||||
|
|
||||||
interface SqlObjectPropertiesProps {
|
|
||||||
object: SqlObject | null
|
|
||||||
type: SqlObjectType | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SqlObjectProperties = ({ object, type }: SqlObjectPropertiesProps) => {
|
const SqlObjectProperties = ({ object }: SqlObjectPropertiesProps) => {
|
||||||
const { translate } = useLocalization()
|
if (!object) {
|
||||||
|
|
||||||
if (!object || !type) {
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 text-center text-gray-500">
|
<div className="flex items-center justify-center h-full text-gray-400 text-sm">
|
||||||
{translate('::App.Platform.SelectAnObjectToViewProperties')}
|
Select an object to view properties
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const PropertyRow = ({ label, value }: { label: string; value: any }) => (
|
|
||||||
<div className="mb-3">
|
|
||||||
<div className="text-xs text-gray-500 dark:text-gray-400 mb-1">{label}</div>
|
|
||||||
<div className="text-sm font-medium">{value || '-'}</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
const getObjectTypeName = () => {
|
|
||||||
switch (type) {
|
|
||||||
case 1:
|
|
||||||
return translate('::App.Platform.Query')
|
|
||||||
case 2:
|
|
||||||
return translate('::App.Platform.StoredProcedure')
|
|
||||||
case 3:
|
|
||||||
return translate('::App.Platform.View')
|
|
||||||
case 4:
|
|
||||||
return translate('::App.Platform.Function')
|
|
||||||
default:
|
|
||||||
return translate('::App.Platform.Object')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStatusBadge = (status: number) => {
|
|
||||||
switch (status) {
|
|
||||||
case 1:
|
|
||||||
return <span className="px-2 py-1 text-xs rounded bg-gray-200 dark:bg-gray-700">{translate('::App.Platform.Draft')}</span>
|
|
||||||
case 2:
|
|
||||||
return <span className="px-2 py-1 text-xs rounded bg-green-200 dark:bg-green-700">{translate('::App.Platform.Active')}</span>
|
|
||||||
case 3:
|
|
||||||
return <span className="px-2 py-1 text-xs rounded bg-orange-200 dark:bg-orange-700">{translate('::App.Platform.Archived')}</span>
|
|
||||||
default:
|
|
||||||
return <span className="px-2 py-1 text-xs rounded bg-gray-200 dark:bg-gray-700">{translate('::App.Platform.Unknown')}</span>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderCommonProperties = () => (
|
|
||||||
<>
|
|
||||||
<PropertyRow label={translate('::App.Platform.ObjectType')} value={getObjectTypeName()} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.ID')} value={object.id} />
|
|
||||||
{object.creationTime && (
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.Created')}
|
|
||||||
value={dayjs(object.creationTime).format('DD/MM/YYYY HH:mm')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{object.lastModificationTime && (
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.Modified')}
|
|
||||||
value={dayjs(object.lastModificationTime).format('DD/MM/YYYY HH:mm')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const renderQueryProperties = () => {
|
|
||||||
const query = object as SqlQueryDto
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="p-4 text-sm">
|
||||||
<PropertyRow label={translate('::App.Platform.Code')} value={query.code} />
|
<pre className="text-xs text-gray-600 dark:text-gray-400 overflow-auto">
|
||||||
<PropertyRow label={translate('::App.Platform.Name')} value={query.name} />
|
{JSON.stringify(object, null, 2)}
|
||||||
<PropertyRow label={translate('::App.Platform.Description')} value={query.description} />
|
</pre>
|
||||||
<PropertyRow label={translate('::App.Platform.DataSource')} value={query.dataSourceCode} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Status')} value={getStatusBadge(query.status)} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Category')} value={query.category} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Tags')} value={query.tags} />
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.ModifiesData')}
|
|
||||||
value={query.isModifyingData ? translate('::App.Platform.Yes') : translate('::App.Platform.No')}
|
|
||||||
/>
|
|
||||||
<PropertyRow label={translate('::App.Platform.ExecutionCount')} value={query.executionCount} />
|
|
||||||
{query.lastExecutedAt && (
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.LastExecuted')}
|
|
||||||
value={dayjs(query.lastExecutedAt).format('DD/MM/YYYY HH:mm')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{renderCommonProperties()}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderStoredProcedureProperties = () => {
|
|
||||||
const sp = object as SqlStoredProcedureDto
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<PropertyRow label={translate('::App.Platform.ProcedureName')} value={sp.procedureName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Schema')} value={sp.schemaName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.DisplayName')} value={sp.displayName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Description')} value={sp.description} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.DataSource')} value={sp.dataSourceCode} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Status')} value={getStatusBadge(sp.status)} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Category')} value={sp.category} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Deployed')} value={sp.isDeployed ? translate('::App.Platform.Yes') : translate('::App.Platform.No')} />
|
|
||||||
{sp.lastDeployedAt && (
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.LastDeployed')}
|
|
||||||
value={dayjs(sp.lastDeployedAt).format('DD/MM/YYYY HH:mm')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{renderCommonProperties()}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderViewProperties = () => {
|
|
||||||
const view = object as SqlViewDto
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<PropertyRow label={translate('::App.Platform.ViewName')} value={view.viewName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Schema')} value={view.schemaName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.DisplayName')} value={view.displayName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Description')} value={view.description} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.DataSource')} value={view.dataSourceCode} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Status')} value={getStatusBadge(view.status)} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Category')} value={view.category} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Deployed')} value={view.isDeployed ? translate('::App.Platform.Yes') : translate('::App.Platform.No')} />
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.SchemaBinding')}
|
|
||||||
value={view.withSchemaBinding ? translate('::App.Platform.Yes') : translate('::App.Platform.No')}
|
|
||||||
/>
|
|
||||||
{view.lastDeployedAt && (
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.LastDeployed')}
|
|
||||||
value={dayjs(view.lastDeployedAt).format('DD/MM/YYYY HH:mm')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{renderCommonProperties()}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderFunctionProperties = () => {
|
|
||||||
const func = object as SqlFunctionDto
|
|
||||||
const getFunctionType = (funcType: number) => {
|
|
||||||
switch (funcType) {
|
|
||||||
case 1:
|
|
||||||
return translate('::App.Platform.ScalarFunction')
|
|
||||||
case 2:
|
|
||||||
return translate('::App.Platform.TableValuedFunction')
|
|
||||||
case 3:
|
|
||||||
return translate('::App.Platform.InlineTableValuedFunction')
|
|
||||||
default:
|
|
||||||
return translate('::App.Platform.Unknown')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<PropertyRow label={translate('::App.Platform.FunctionName')} value={func.functionName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Schema')} value={func.schemaName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.DisplayName')} value={func.displayName} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Description')} value={func.description} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.FunctionType')} value={getFunctionType(func.functionType)} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.ReturnType')} value={func.returnType} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.DataSource')} value={func.dataSourceCode} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Status')} value={getStatusBadge(func.status)} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Category')} value={func.category} />
|
|
||||||
<PropertyRow label={translate('::App.Platform.Deployed')} value={func.isDeployed ? translate('::App.Platform.Yes') : translate('::App.Platform.No')} />
|
|
||||||
{func.lastDeployedAt && (
|
|
||||||
<PropertyRow
|
|
||||||
label={translate('::App.Platform.LastDeployed')}
|
|
||||||
value={dayjs(func.lastDeployedAt).format('DD/MM/YYYY HH:mm')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{renderCommonProperties()}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="h-full flex flex-col">
|
|
||||||
<div className="mb-4 pb-2 border-b">
|
|
||||||
<h6 className="font-bold">{translate('::App.Platform.Properties')}</h6>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex-1 overflow-auto p-2">
|
|
||||||
{type === 1 && renderQueryProperties()}
|
|
||||||
{type === 2 && renderStoredProcedureProperties()}
|
|
||||||
{type === 3 && renderViewProperties()}
|
|
||||||
{type === 4 && renderFunctionProperties()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,31 @@
|
||||||
import { useState, useCallback, useEffect, useRef } from 'react'
|
import { useState, useCallback, useEffect, useRef } from 'react'
|
||||||
import { Button, Dialog, Input, Notification, toast } from '@/components/ui'
|
import { Button, Dialog, Notification, toast } from '@/components/ui'
|
||||||
import Container from '@/components/shared/Container'
|
import Container from '@/components/shared/Container'
|
||||||
import AdaptableCard from '@/components/shared/AdaptableCard'
|
|
||||||
import { getDataSources } from '@/services/data-source.service'
|
import { getDataSources } from '@/services/data-source.service'
|
||||||
import type { DataSourceDto } from '@/proxy/data-source'
|
import type { DataSourceDto } from '@/proxy/data-source'
|
||||||
import type {
|
import type { SqlQueryExecutionResultDto } from '@/proxy/sql-query-manager/models'
|
||||||
SqlFunctionDto,
|
|
||||||
SqlQueryDto,
|
|
||||||
SqlStoredProcedureDto,
|
|
||||||
SqlViewDto,
|
|
||||||
SqlQueryExecutionResultDto,
|
|
||||||
} from '@/proxy/sql-query-manager/models'
|
|
||||||
import { SqlObjectType } from '@/proxy/sql-query-manager/models'
|
|
||||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||||
import { FaDatabase, FaPlay, FaSave, FaCloudUploadAlt, FaCode } from 'react-icons/fa'
|
import { FaDatabase, FaPlay, FaFileAlt } from 'react-icons/fa'
|
||||||
import { FaCheckCircle } from 'react-icons/fa'
|
import { FaCheckCircle } from 'react-icons/fa'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
import SqlObjectExplorer from './SqlObjectExplorer'
|
import SqlObjectExplorer from './SqlObjectExplorer'
|
||||||
import SqlEditor, { SqlEditorRef } from './SqlEditor'
|
import SqlEditor, { SqlEditorRef } from './SqlEditor'
|
||||||
import SqlResultsGrid from './SqlResultsGrid'
|
import SqlResultsGrid from './SqlResultsGrid'
|
||||||
import SqlObjectProperties from './SqlObjectProperties'
|
|
||||||
import SqlTableDesignerDialog from './SqlTableDesignerDialog'
|
import SqlTableDesignerDialog from './SqlTableDesignerDialog'
|
||||||
import { Splitter } from '@/components/codeLayout/Splitter'
|
import { Splitter } from '@/components/codeLayout/Splitter'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
import { APP_NAME } from '@/constants/app.constant'
|
import { APP_NAME } from '@/constants/app.constant'
|
||||||
|
|
||||||
export type SqlObject = SqlFunctionDto | SqlQueryDto | SqlStoredProcedureDto | SqlViewDto
|
|
||||||
|
|
||||||
interface SqlManagerState {
|
interface SqlManagerState {
|
||||||
dataSources: DataSourceDto[]
|
dataSources: DataSourceDto[]
|
||||||
selectedDataSource: string | null
|
selectedDataSource: string | null
|
||||||
selectedObject: SqlObject | null
|
|
||||||
selectedObjectType: SqlObjectType | null
|
|
||||||
editorContent: string
|
editorContent: string
|
||||||
isExecuting: boolean
|
isExecuting: boolean
|
||||||
executionResult: SqlQueryExecutionResultDto | null
|
executionResult: SqlQueryExecutionResultDto | null
|
||||||
showProperties: boolean
|
showProperties: boolean
|
||||||
isDirty: boolean
|
isDirty: boolean
|
||||||
tableColumns: any | null
|
tableColumns: any | null
|
||||||
isSaved: boolean
|
|
||||||
refreshTrigger: number
|
refreshTrigger: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,8 +37,6 @@ const SqlQueryManager = () => {
|
||||||
const [state, setState] = useState<SqlManagerState>({
|
const [state, setState] = useState<SqlManagerState>({
|
||||||
dataSources: [],
|
dataSources: [],
|
||||||
selectedDataSource: tenantName ?? null,
|
selectedDataSource: tenantName ?? null,
|
||||||
selectedObject: null,
|
|
||||||
selectedObjectType: null,
|
|
||||||
editorContent: '',
|
editorContent: '',
|
||||||
isExecuting: false,
|
isExecuting: false,
|
||||||
refreshTrigger: 0,
|
refreshTrigger: 0,
|
||||||
|
|
@ -60,23 +44,17 @@ const SqlQueryManager = () => {
|
||||||
showProperties: false,
|
showProperties: false,
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
tableColumns: null,
|
tableColumns: null,
|
||||||
isSaved: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const [showSaveDialog, setShowSaveDialog] = useState(false)
|
|
||||||
const [saveDialogData, setSaveDialogData] = useState({
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
detectedType: '',
|
|
||||||
detectedName: '',
|
|
||||||
isExistingObject: false,
|
|
||||||
})
|
|
||||||
const [showTemplateConfirmDialog, setShowTemplateConfirmDialog] = useState(false)
|
const [showTemplateConfirmDialog, setShowTemplateConfirmDialog] = useState(false)
|
||||||
const [pendingTemplate, setPendingTemplate] = useState<{ content: string; type: string } | null>(
|
const [pendingTemplate, setPendingTemplate] = useState<{ content: string; type: string } | null>(
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
const [showTableDesignerDialog, setShowTableDesignerDialog] = useState(false)
|
const [showTableDesignerDialog, setShowTableDesignerDialog] = useState(false)
|
||||||
const [designTableData, setDesignTableData] = useState<{ schemaName: string; tableName: string } | null>(null)
|
const [designTableData, setDesignTableData] = useState<{
|
||||||
|
schemaName: string
|
||||||
|
tableName: string
|
||||||
|
} | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadDataSources()
|
loadDataSources()
|
||||||
|
|
@ -107,7 +85,6 @@ const SqlQueryManager = () => {
|
||||||
setState((prev) => ({
|
setState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
selectedDataSource: dataSource.code ?? null,
|
selectedDataSource: dataSource.code ?? null,
|
||||||
selectedObject: null,
|
|
||||||
editorContent: '',
|
editorContent: '',
|
||||||
executionResult: null,
|
executionResult: null,
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
|
|
@ -124,111 +101,11 @@ const SqlQueryManager = () => {
|
||||||
setShowTableDesignerDialog(true)
|
setShowTableDesignerDialog(true)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleObjectSelect = useCallback(
|
|
||||||
async (object: SqlObject | null, objectType: SqlObjectType | null) => {
|
|
||||||
if (state.isDirty) {
|
|
||||||
if (!confirm(translate('::App.Platform.UnsavedChangesConfirmation'))) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = ''
|
|
||||||
if (object) {
|
|
||||||
if (objectType === 1) {
|
|
||||||
// Query
|
|
||||||
content = (object as SqlQueryDto).queryText || ''
|
|
||||||
} else if (objectType === 2) {
|
|
||||||
// Stored Procedure
|
|
||||||
const sp = object as SqlStoredProcedureDto
|
|
||||||
if (sp.isCustom) {
|
|
||||||
content = sp.procedureBody || ''
|
|
||||||
} else {
|
|
||||||
// Native SP - fetch definition from SQL Server
|
|
||||||
try {
|
|
||||||
const result = await sqlObjectManagerService.getNativeObjectDefinition(
|
|
||||||
state.selectedDataSource || '',
|
|
||||||
sp.schemaName,
|
|
||||||
sp.procedureName
|
|
||||||
)
|
|
||||||
content = result.data || ''
|
|
||||||
} catch (error) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{translate('::App.Platform.FailedToLoadDefinition')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (objectType === 3) {
|
|
||||||
// View
|
|
||||||
const view = object as SqlViewDto
|
|
||||||
if (view.isCustom) {
|
|
||||||
content = view.viewDefinition || ''
|
|
||||||
} else {
|
|
||||||
// Native View - fetch definition from SQL Server
|
|
||||||
try {
|
|
||||||
const result = await sqlObjectManagerService.getNativeObjectDefinition(
|
|
||||||
state.selectedDataSource || '',
|
|
||||||
view.schemaName,
|
|
||||||
view.viewName
|
|
||||||
)
|
|
||||||
content = result.data || ''
|
|
||||||
} catch (error) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{translate('::App.Platform.FailedToLoadDefinition')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (objectType === 4) {
|
|
||||||
// Function
|
|
||||||
const func = object as SqlFunctionDto
|
|
||||||
if (func.isCustom) {
|
|
||||||
content = func.functionBody || ''
|
|
||||||
} else {
|
|
||||||
// Native Function - fetch definition from SQL Server
|
|
||||||
try {
|
|
||||||
const result = await sqlObjectManagerService.getNativeObjectDefinition(
|
|
||||||
state.selectedDataSource || '',
|
|
||||||
func.schemaName,
|
|
||||||
func.functionName
|
|
||||||
)
|
|
||||||
content = result.data || ''
|
|
||||||
} catch (error) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{translate('::App.Platform.FailedToLoadDefinition')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setState((prev) => ({
|
|
||||||
...prev,
|
|
||||||
selectedObject: object,
|
|
||||||
selectedObjectType: objectType,
|
|
||||||
editorContent: content,
|
|
||||||
executionResult: null,
|
|
||||||
tableColumns: null,
|
|
||||||
isDirty: false,
|
|
||||||
isSaved: false,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
[state.isDirty, state.selectedDataSource, translate],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleEditorChange = useCallback((value: string | undefined) => {
|
const handleEditorChange = useCallback((value: string | undefined) => {
|
||||||
setState((prev) => ({
|
setState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
editorContent: value || '',
|
editorContent: value || '',
|
||||||
isDirty: true,
|
isDirty: true,
|
||||||
isSaved: false,
|
|
||||||
}))
|
}))
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
@ -350,69 +227,14 @@ GO`,
|
||||||
return templates[templateType] || templates['select']
|
return templates[templateType] || templates['select']
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQL analiz fonksiyonu - SQL metnini analiz edip nesne türünü ve adını tespit eder
|
const applyTemplate = useCallback((templateContent: string) => {
|
||||||
const detectSqlObject = (sql: string): { type: string; name: string } => {
|
|
||||||
const upperSql = sql.trim().toUpperCase()
|
|
||||||
|
|
||||||
// VIEW tespiti
|
|
||||||
if (upperSql.includes('CREATE VIEW') || upperSql.includes('ALTER VIEW')) {
|
|
||||||
// Son kelimeyi al (schema varsa sonraki kelime, yoksa ilk kelime)
|
|
||||||
const viewMatch = sql.match(
|
|
||||||
/(?:CREATE|ALTER)\s+VIEW\s+(?:[\[\]]*\w+[\[\]]*\.)?\s*[\[]?(\w+)[\]]?/i,
|
|
||||||
)
|
|
||||||
return {
|
|
||||||
type: 'View',
|
|
||||||
name: viewMatch ? viewMatch[1] : '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// STORED PROCEDURE tespiti
|
|
||||||
if (
|
|
||||||
upperSql.includes('CREATE PROCEDURE') ||
|
|
||||||
upperSql.includes('CREATE PROC') ||
|
|
||||||
upperSql.includes('ALTER PROCEDURE') ||
|
|
||||||
upperSql.includes('ALTER PROC')
|
|
||||||
) {
|
|
||||||
const procMatch = sql.match(
|
|
||||||
/(?:CREATE|ALTER)\s+(?:PROCEDURE|PROC)\s+(?:[\[\]]*\w+[\[\]]*\.)?\s*[\[]?(\w+)[\]]?/i,
|
|
||||||
)
|
|
||||||
return {
|
|
||||||
type: 'StoredProcedure',
|
|
||||||
name: procMatch ? procMatch[1] : '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FUNCTION tespiti
|
|
||||||
if (upperSql.includes('CREATE FUNCTION') || upperSql.includes('ALTER FUNCTION')) {
|
|
||||||
const funcMatch = sql.match(
|
|
||||||
/(?:CREATE|ALTER)\s+FUNCTION\s+(?:[\[\]]*\w+[\[\]]*\.)?\s*[\[]?(\w+)[\]]?/i,
|
|
||||||
)
|
|
||||||
return {
|
|
||||||
type: 'Function',
|
|
||||||
name: funcMatch ? funcMatch[1] : '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default: Query
|
|
||||||
return {
|
|
||||||
type: 'Query',
|
|
||||||
name: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const applyTemplate = useCallback(
|
|
||||||
(templateContent: string) => {
|
|
||||||
setState((prev) => ({
|
setState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
editorContent: templateContent,
|
editorContent: templateContent,
|
||||||
selectedObject: null,
|
|
||||||
selectedObjectType: null,
|
|
||||||
executionResult: null,
|
executionResult: null,
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
}))
|
}))
|
||||||
},
|
}, [])
|
||||||
[],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleUseTemplateFromDialog = useCallback(
|
const handleUseTemplateFromDialog = useCallback(
|
||||||
(templateContent: string, templateType: string) => {
|
(templateContent: string, templateType: string) => {
|
||||||
|
|
@ -464,6 +286,16 @@ GO`,
|
||||||
setPendingTemplate(null)
|
setPendingTemplate(null)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const handleNewQuery = useCallback(() => {
|
||||||
|
setState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
editorContent: '',
|
||||||
|
executionResult: null,
|
||||||
|
tableColumns: null,
|
||||||
|
isDirty: false,
|
||||||
|
}))
|
||||||
|
}, [])
|
||||||
|
|
||||||
const handleExecute = async () => {
|
const handleExecute = async () => {
|
||||||
if (!state.selectedDataSource) {
|
if (!state.selectedDataSource) {
|
||||||
toast.push(
|
toast.push(
|
||||||
|
|
@ -532,246 +364,29 @@ GO`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleViewDefinition = async (schemaName: string, objectName: string) => {
|
||||||
if (!state.selectedDataSource) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="warning" title={translate('::App.Platform.Warning')}>
|
|
||||||
{translate('::App.Platform.PleaseSelectDataSource')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state.editorContent?.trim()) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="warning" title={translate('::App.Platform.Warning')}>
|
|
||||||
{translate('::App.Platform.PleaseEnterContentToSave')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.selectedObject && state.selectedObjectType) {
|
|
||||||
// Update existing object - open dialog with existing data
|
|
||||||
const typeMap: Record<SqlObjectType, string> = {
|
|
||||||
[SqlObjectType.Query]: 'Query',
|
|
||||||
[SqlObjectType.View]: 'View',
|
|
||||||
[SqlObjectType.StoredProcedure]: 'StoredProcedure',
|
|
||||||
[SqlObjectType.Function]: 'Function',
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get name based on object type
|
|
||||||
let objectName = ''
|
|
||||||
if ('viewName' in state.selectedObject) {
|
|
||||||
objectName = state.selectedObject.viewName || state.selectedObject.displayName || ''
|
|
||||||
} else if ('procedureName' in state.selectedObject) {
|
|
||||||
objectName = state.selectedObject.procedureName || state.selectedObject.displayName || ''
|
|
||||||
} else if ('functionName' in state.selectedObject) {
|
|
||||||
objectName = state.selectedObject.functionName || state.selectedObject.displayName || ''
|
|
||||||
} else if ('name' in state.selectedObject) {
|
|
||||||
objectName = state.selectedObject.name || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
setSaveDialogData({
|
|
||||||
name: objectName,
|
|
||||||
description: state.selectedObject.description || '',
|
|
||||||
detectedType: typeMap[state.selectedObjectType] || '',
|
|
||||||
detectedName: objectName,
|
|
||||||
isExistingObject: true,
|
|
||||||
})
|
|
||||||
setShowSaveDialog(true)
|
|
||||||
} else {
|
|
||||||
// New object - analyze SQL and show dialog with detection
|
|
||||||
const detection = detectSqlObject(state.editorContent)
|
|
||||||
setSaveDialogData({
|
|
||||||
name: detection.name,
|
|
||||||
description: '',
|
|
||||||
detectedType: detection.type,
|
|
||||||
detectedName: detection.name,
|
|
||||||
isExistingObject: false,
|
|
||||||
})
|
|
||||||
setShowSaveDialog(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCreateNewQuery = async () => {
|
|
||||||
if (!state.selectedDataSource || !saveDialogData.name) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Smart save ile kaydet
|
|
||||||
const result = await sqlObjectManagerService.smartSave({
|
|
||||||
sqlText: state.editorContent,
|
|
||||||
dataSourceCode: state.selectedDataSource || '',
|
|
||||||
name: saveDialogData.name,
|
|
||||||
description: saveDialogData.description,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Kaydedilen objeyi state'e set et
|
|
||||||
const savedObject: any = {
|
|
||||||
id: result.data.objectId,
|
|
||||||
displayName: saveDialogData.name,
|
|
||||||
description: saveDialogData.description,
|
|
||||||
isDeployed: result.data.deployed,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectType'a göre ekstra alanlar ekle
|
|
||||||
let objectType: SqlObjectType | null = null
|
|
||||||
if (result.data.objectType === 'View') {
|
|
||||||
objectType = SqlObjectType.View
|
|
||||||
savedObject.viewName = saveDialogData.name
|
|
||||||
savedObject.viewDefinition = state.editorContent
|
|
||||||
} else if (result.data.objectType === 'StoredProcedure') {
|
|
||||||
objectType = SqlObjectType.StoredProcedure
|
|
||||||
savedObject.procedureName = saveDialogData.name
|
|
||||||
savedObject.procedureBody = state.editorContent
|
|
||||||
} else if (result.data.objectType === 'Function') {
|
|
||||||
objectType = SqlObjectType.Function
|
|
||||||
savedObject.functionName = saveDialogData.name
|
|
||||||
savedObject.functionBody = state.editorContent
|
|
||||||
} else if (result.data.objectType === 'Query') {
|
|
||||||
objectType = SqlObjectType.Query
|
|
||||||
savedObject.queryText = state.editorContent
|
|
||||||
}
|
|
||||||
|
|
||||||
setState((prev) => ({
|
|
||||||
...prev,
|
|
||||||
isDirty: false,
|
|
||||||
isSaved: true,
|
|
||||||
selectedObject: savedObject,
|
|
||||||
selectedObjectType: objectType,
|
|
||||||
refreshTrigger: prev.refreshTrigger + 1,
|
|
||||||
}))
|
|
||||||
setShowSaveDialog(false)
|
|
||||||
|
|
||||||
toast.push(
|
|
||||||
<Notification type="success" title={translate('::App.Platform.Success')}>
|
|
||||||
{result.data.message || translate('::App.Platform.SavedSuccessfully')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
} catch (error: any) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{error.response?.data?.error?.message || translate('::App.Platform.FailedToSaveQuery')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeploy = async () => {
|
|
||||||
if (!state.selectedObject || !state.selectedObjectType) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="warning" title={translate('::App.Platform.Warning')}>
|
|
||||||
{translate('::App.Platform.PleaseSelectAnObjectToDeploy')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!state.selectedObject.id) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
const objectId = state.selectedObject.id
|
|
||||||
let result: any
|
|
||||||
|
|
||||||
switch (state.selectedObjectType) {
|
|
||||||
case SqlObjectType.StoredProcedure:
|
|
||||||
result = await sqlObjectManagerService.deployStoredProcedure({
|
|
||||||
id: objectId,
|
|
||||||
dropIfExists: true,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case SqlObjectType.View:
|
|
||||||
result = await sqlObjectManagerService.deployView({ id: objectId, dropIfExists: true })
|
|
||||||
break
|
|
||||||
case SqlObjectType.Function:
|
|
||||||
result = await sqlObjectManagerService.deployFunction({
|
|
||||||
id: objectId,
|
|
||||||
dropIfExists: true,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
toast.push(
|
|
||||||
<Notification type="warning" title={translate('::App.Platform.Warning')}>
|
|
||||||
{translate('::App.Platform.ThisObjectTypeCannotBeDeployed')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update selectedObject's isDeployed status
|
|
||||||
setState((prev) => ({
|
|
||||||
...prev,
|
|
||||||
selectedObject: prev.selectedObject ? { ...prev.selectedObject, isDeployed: true } : null,
|
|
||||||
refreshTrigger: prev.refreshTrigger + 1,
|
|
||||||
}))
|
|
||||||
|
|
||||||
toast.push(
|
|
||||||
<Notification type="success" title={translate('::App.Platform.Success')}>
|
|
||||||
{translate('::App.Platform.ObjectDeployedSuccessfully')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
} catch (error: any) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
|
||||||
{error.response?.data?.error?.message || translate('::App.Platform.FailedToDeployObject')}
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-center' },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleShowTableColumns = async (schemaName: string, tableName: string) => {
|
|
||||||
if (!state.selectedDataSource) return
|
if (!state.selectedDataSource) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await sqlObjectManagerService.getTableColumns(
|
const result = await sqlObjectManagerService.getNativeObjectDefinition(
|
||||||
state.selectedDataSource || '',
|
state.selectedDataSource,
|
||||||
schemaName,
|
schemaName,
|
||||||
tableName,
|
objectName,
|
||||||
)
|
)
|
||||||
|
if (result.data) {
|
||||||
// Transform API response to match display format
|
const definition = result.data.replace(/\bCREATE\b/i, 'ALTER')
|
||||||
const transformedData = response.data.map((col: any) => ({
|
|
||||||
ColumnName: col.columnName,
|
|
||||||
DataType: col.dataType,
|
|
||||||
MaxLength: col.maxLength || '-',
|
|
||||||
IsNullable: col.isNullable,
|
|
||||||
IsPrimaryKey: col.isPrimaryKey || false,
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Create a result object that looks like execution result for display
|
|
||||||
const columnsResult = {
|
|
||||||
success: true,
|
|
||||||
message: `Columns for ${schemaName}.${tableName}`,
|
|
||||||
data: transformedData,
|
|
||||||
rowsAffected: transformedData.length,
|
|
||||||
executionTimeMs: 0,
|
|
||||||
metadata: {
|
|
||||||
columns: [
|
|
||||||
{ name: 'ColumnName', dataType: 'string' },
|
|
||||||
{ name: 'DataType', dataType: 'string' },
|
|
||||||
{ name: 'MaxLength', dataType: 'string' },
|
|
||||||
{ name: 'IsNullable', dataType: 'boolean' },
|
|
||||||
{ name: 'IsPrimaryKey', dataType: 'boolean' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
setState((prev) => ({
|
setState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
tableColumns: columnsResult,
|
editorContent: definition,
|
||||||
executionResult: null, // Clear query results when showing columns
|
executionResult: null,
|
||||||
|
tableColumns: null,
|
||||||
|
isDirty: false,
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.push(
|
toast.push(
|
||||||
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
<Notification type="danger" title={translate('::App.Platform.Error')}>
|
||||||
{error.response?.data?.error?.message || translate('::App.Platform.FailedToLoadColumns')}
|
{error.response?.data?.error?.message ||
|
||||||
|
translate('::App.Platform.FailedToLoadDefinition')}
|
||||||
</Notification>,
|
</Notification>,
|
||||||
{ placement: 'top-center' },
|
{ placement: 'top-center' },
|
||||||
)
|
)
|
||||||
|
|
@ -779,14 +394,14 @@ GO`,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className="h-full overflow-hidden">
|
<Container className="flex flex-col overflow-hidden" style={{ height: 'calc(100vh - 130px)' }}>
|
||||||
<Helmet
|
<Helmet
|
||||||
titleTemplate={`%s | ${APP_NAME}`}
|
titleTemplate={`%s | ${APP_NAME}`}
|
||||||
title={translate('::' + 'App.SqlQueryManager')}
|
title={translate('::' + 'App.SqlQueryManager')}
|
||||||
defaultTitle={APP_NAME}
|
defaultTitle={APP_NAME}
|
||||||
></Helmet>
|
></Helmet>
|
||||||
|
|
||||||
<div className="flex flex-col h-full p-1">
|
<div className="flex flex-col flex-1 min-h-0 p-1">
|
||||||
{/* Toolbar */}
|
{/* Toolbar */}
|
||||||
<div className="flex-shrink-0 shadow-sm mb-4">
|
<div className="flex-shrink-0 shadow-sm mb-4">
|
||||||
<div className="flex items-center justify-between px-1 py-1">
|
<div className="flex items-center justify-between px-1 py-1">
|
||||||
|
|
@ -813,6 +428,15 @@ GO`,
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="default"
|
||||||
|
icon={<FaFileAlt />}
|
||||||
|
onClick={handleNewQuery}
|
||||||
|
className="shadow-sm"
|
||||||
|
>
|
||||||
|
{translate('::App.Platform.NewQuery') || 'New Query'}
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
|
|
@ -826,40 +450,6 @@ GO`,
|
||||||
{translate('::App.Platform.Execute')}
|
{translate('::App.Platform.Execute')}
|
||||||
<span className="ml-1 text-xs opacity-75">(F5)</span>
|
<span className="ml-1 text-xs opacity-75">(F5)</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="solid"
|
|
||||||
icon={<FaSave />}
|
|
||||||
onClick={handleSave}
|
|
||||||
disabled={
|
|
||||||
!state.selectedDataSource ||
|
|
||||||
!state.editorContent?.trim() ||
|
|
||||||
(state.isSaved && !state.isDirty) ||
|
|
||||||
!state.executionResult?.success
|
|
||||||
}
|
|
||||||
className="shadow-sm"
|
|
||||||
>
|
|
||||||
{translate('::App.Platform.Save')}
|
|
||||||
<span className="ml-1 text-xs opacity-75">(Ctrl+S)</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="solid"
|
|
||||||
color="green-600"
|
|
||||||
icon={<FaCloudUploadAlt />}
|
|
||||||
onClick={handleDeploy}
|
|
||||||
disabled={
|
|
||||||
!state.selectedObject ||
|
|
||||||
!state.selectedObjectType ||
|
|
||||||
state.selectedObjectType === SqlObjectType.Query ||
|
|
||||||
(state.selectedObject &&
|
|
||||||
'isDeployed' in state.selectedObject &&
|
|
||||||
state.selectedObject.isDeployed)
|
|
||||||
}
|
|
||||||
className="shadow-sm"
|
|
||||||
>
|
|
||||||
{translate('::App.Platform.Deploy')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -867,26 +457,22 @@ GO`,
|
||||||
{/* Main Content Area */}
|
{/* Main Content Area */}
|
||||||
<div className="flex-1 flex min-h-0">
|
<div className="flex-1 flex min-h-0">
|
||||||
{/* Left Panel - Object Explorer */}
|
{/* Left Panel - Object Explorer */}
|
||||||
<div className="w-1/3 flex-shrink-0 flex flex-col min-h-0 mr-4">
|
<div className="w-1/3 flex-shrink-0 flex flex-col min-h-0 mr-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-600 shadow">
|
||||||
<AdaptableCard className="h-full" bodyClass="p-0">
|
<div className="border-b px-4 py-2 bg-gray-50 dark:bg-gray-800 flex-shrink-0 rounded-t-lg">
|
||||||
<div className="h-full flex flex-col">
|
|
||||||
<div className="border-b px-4 py-2 bg-gray-50 dark:bg-gray-800 flex-shrink-0">
|
|
||||||
<h6 className="font-semibold text-sm">
|
<h6 className="font-semibold text-sm">
|
||||||
{translate('::App.Platform.ObjectExplorer')}
|
{translate('::App.Platform.ObjectExplorer')}
|
||||||
</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex-1 min-h-0 flex flex-col overflow-hidden">
|
||||||
<SqlObjectExplorer
|
<SqlObjectExplorer
|
||||||
dataSource={state.selectedDataSource}
|
dataSource={state.selectedDataSource}
|
||||||
onObjectSelect={handleObjectSelect}
|
|
||||||
selectedObject={state.selectedObject}
|
|
||||||
onTemplateSelect={handleTemplateSelect}
|
onTemplateSelect={handleTemplateSelect}
|
||||||
onShowTableColumns={handleShowTableColumns}
|
onViewDefinition={handleViewDefinition}
|
||||||
refreshTrigger={state.refreshTrigger}
|
refreshTrigger={state.refreshTrigger}
|
||||||
onNewTable={handleNewTable}
|
onNewTable={handleNewTable}
|
||||||
onDesignTable={handleDesignTable}
|
onDesignTable={handleDesignTable}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</AdaptableCard>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Center Panel - Editor and Results */}
|
{/* Center Panel - Editor and Results */}
|
||||||
|
|
@ -905,7 +491,6 @@ GO`,
|
||||||
value={state.editorContent}
|
value={state.editorContent}
|
||||||
onChange={handleEditorChange}
|
onChange={handleEditorChange}
|
||||||
onExecute={handleExecute}
|
onExecute={handleExecute}
|
||||||
onSave={handleSave}
|
|
||||||
readOnly={state.isExecuting}
|
readOnly={state.isExecuting}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -958,20 +543,12 @@ GO`,
|
||||||
value={state.editorContent}
|
value={state.editorContent}
|
||||||
onChange={handleEditorChange}
|
onChange={handleEditorChange}
|
||||||
onExecute={handleExecute}
|
onExecute={handleExecute}
|
||||||
onSave={handleSave}
|
|
||||||
readOnly={state.isExecuting}
|
readOnly={state.isExecuting}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Panel - Properties (Optional) */}
|
|
||||||
{state.showProperties && state.selectedObject && (
|
|
||||||
<div className="w-80 flex-shrink-0 flex flex-col min-h-0">
|
|
||||||
<SqlObjectProperties object={state.selectedObject} type={state.selectedObjectType} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -1008,85 +585,6 @@ GO`,
|
||||||
setState((prev) => ({ ...prev, refreshTrigger: prev.refreshTrigger + 1 }))
|
setState((prev) => ({ ...prev, refreshTrigger: prev.refreshTrigger + 1 }))
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Save Dialog */}
|
|
||||||
<Dialog
|
|
||||||
isOpen={showSaveDialog}
|
|
||||||
onClose={() => setShowSaveDialog(false)}
|
|
||||||
onRequestClose={() => setShowSaveDialog(false)}
|
|
||||||
>
|
|
||||||
<h5 className="mb-4">{translate('::App.Platform.SaveQuery')}</h5>
|
|
||||||
<div className="space-y-4">
|
|
||||||
{/* Detected Object Type */}
|
|
||||||
{saveDialogData.detectedType && (
|
|
||||||
<div className="p-3 bg-blue-50 dark:bg-blue-900/20 rounded-md border border-blue-200 dark:border-blue-800">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<FaCheckCircle className="text-blue-600 dark:text-blue-400 text-xl" />
|
|
||||||
<div>
|
|
||||||
<div className="text-sm font-semibold text-blue-900 dark:text-blue-100">
|
|
||||||
{translate('::App.Platform.DetectedObjectType')}
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-blue-700 dark:text-blue-300">
|
|
||||||
{saveDialogData.detectedType === 'View' && translate('::App.Platform.View')}
|
|
||||||
{saveDialogData.detectedType === 'StoredProcedure' &&
|
|
||||||
translate('::App.Platform.StoredProcedure')}
|
|
||||||
{saveDialogData.detectedType === 'Function' &&
|
|
||||||
translate('::App.Platform.Function')}
|
|
||||||
{saveDialogData.detectedType === 'Query' && translate('::App.Platform.Query')}
|
|
||||||
</div>
|
|
||||||
{saveDialogData.detectedName && (
|
|
||||||
<div className="text-xs text-blue-600 dark:text-blue-400 mt-1">
|
|
||||||
{translate('::App.Platform.DetectedName')}:{' '}
|
|
||||||
<span className="font-mono">{saveDialogData.detectedName}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label className="block mb-2">
|
|
||||||
{translate('::App.Platform.Name')} <span className="text-red-500">*</span>
|
|
||||||
{saveDialogData.isExistingObject && (
|
|
||||||
<span className="text-xs text-gray-500 ml-2">
|
|
||||||
({translate('::App.Platform.CannotBeChanged')})
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</label>
|
|
||||||
<Input
|
|
||||||
autoFocus={!saveDialogData.isExistingObject}
|
|
||||||
value={saveDialogData.name}
|
|
||||||
onChange={(e) => setSaveDialogData((prev) => ({ ...prev, name: e.target.value }))}
|
|
||||||
placeholder={saveDialogData.detectedName || translate('::App.Platform.Name')}
|
|
||||||
invalid={!saveDialogData.name.trim()}
|
|
||||||
disabled={saveDialogData.isExistingObject}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block mb-2">{translate('::App.Platform.Description')}</label>
|
|
||||||
<Input
|
|
||||||
value={saveDialogData.description}
|
|
||||||
onChange={(e) =>
|
|
||||||
setSaveDialogData((prev) => ({ ...prev, description: e.target.value }))
|
|
||||||
}
|
|
||||||
placeholder={translate('::App.Platform.Description')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-end gap-2">
|
|
||||||
<Button variant="plain" onClick={() => setShowSaveDialog(false)}>
|
|
||||||
{translate('::Cancel')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
onClick={handleCreateNewQuery}
|
|
||||||
disabled={!saveDialogData.name.trim()}
|
|
||||||
>
|
|
||||||
{translate('::App.Platform.Save')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -957,12 +957,13 @@ const SqlTableDesignerDialog = ({
|
||||||
const STEP_LABELS = ['Sütun Tasarımı', 'Entity Ayarları', 'İlişkiler', 'T-SQL Önizleme']
|
const STEP_LABELS = ['Sütun Tasarımı', 'Entity Ayarları', 'İlişkiler', 'T-SQL Önizleme']
|
||||||
|
|
||||||
const renderStepIndicator = () => (
|
const renderStepIndicator = () => (
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
{STEP_LABELS.map((label, i) => {
|
{STEP_LABELS.map((label, i) => {
|
||||||
const isDone = i < step
|
const isDone = i < step
|
||||||
const isActive = i === step
|
const isActive = i === step
|
||||||
return (
|
return (
|
||||||
<div key={i} className="flex items-center gap-2">
|
<div key={i} className="flex items-center flex-1">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className={`w-7 h-7 rounded-full flex items-center justify-center text-xs font-bold transition-colors
|
className={`w-7 h-7 rounded-full flex items-center justify-center text-xs font-bold transition-colors
|
||||||
${isDone ? 'bg-green-500 text-white' : isActive ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400'}`}
|
${isDone ? 'bg-green-500 text-white' : isActive ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400'}`}
|
||||||
|
|
@ -970,12 +971,13 @@ const SqlTableDesignerDialog = ({
|
||||||
{isDone ? <FaCheck /> : i + 1}
|
{isDone ? <FaCheck /> : i + 1}
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className={`text-sm font-medium ${isActive ? 'text-blue-600 dark:text-blue-400' : 'text-gray-500'}`}
|
className={`text-sm font-medium whitespace-nowrap ${isActive ? 'text-blue-600 dark:text-blue-400' : 'text-gray-500'}`}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
{i < STEP_LABELS.length - 1 && (
|
{i < STEP_LABELS.length - 1 && (
|
||||||
<FaChevronRight className="text-gray-300 dark:text-gray-600 mx-1" />
|
<div className="flex-1 mx-3 h-px bg-gray-200 dark:bg-gray-700" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue