diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs index e17904e..adef427 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Application.Services; @@ -6,47 +5,26 @@ using Volo.Abp.Application.Services; namespace Sozsoft.SqlQueryManager.Application.Contracts; /// -/// 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. /// public interface ISqlObjectManagerAppService : IApplicationService { /// - /// Get all SQL objects for Object Explorer (Queries, SPs, Views, Functions, Tables, Templates) + /// Returns tables (and optionally templates) available on the given data source. /// - /// Data source code to filter objects - /// Combined response with all object types Task GetAllObjectsAsync(string dataSourceCode); - // Query Operations - Task CreateQueryAsync(CreateSqlQueryDto input); - Task UpdateQueryAsync(Guid id, UpdateSqlQueryDto input); - Task DeleteQueryAsync(Guid id); + /// + /// Executes raw T-SQL against the specified data source. + /// Task ExecuteQueryAsync(ExecuteSqlQueryDto input); - Task ExecuteSavedQueryAsync(Guid id); - - // Stored Procedure Operations - Task UpdateStoredProcedureAsync(Guid id, UpdateSqlStoredProcedureDto input); - Task DeleteStoredProcedureAsync(Guid id); - Task DeployStoredProcedureAsync(DeployStoredProcedureDto input); - - // View Operations - Task UpdateViewAsync(Guid id, UpdateSqlViewDto input); - Task DeleteViewAsync(Guid id); - Task DeployViewAsync(DeployViewDto input); - - // Function Operations - Task UpdateFunctionAsync(Guid id, UpdateSqlFunctionDto input); - Task DeleteFunctionAsync(Guid id); - Task DeployFunctionAsync(DeployFunctionDto input); // Database Metadata Operations Task> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName); - + /// /// Gets the SQL definition/body of a native SQL Server object (Stored Procedure, View, or Function) /// Task GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName); - - // Smart Save - Analyzes SQL and saves to appropriate table with auto-deploy - Task SmartSaveAsync(SmartSaveInputDto input); } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SmartSaveDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SmartSaveDto.cs deleted file mode 100644 index 7b3b3b9..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SmartSaveDto.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace Sozsoft.SqlQueryManager.Application.Contracts; - -/// -/// Input for smart save operation -/// -public class SmartSaveInputDto -{ - public string SqlText { get; set; } - public string DataSourceCode { get; set; } - public string Name { get; set; } - public string Description { get; set; } -} - -/// -/// Result of smart save operation -/// -public class SmartSaveResultDto -{ - public string ObjectType { get; set; } - public Guid ObjectId { get; set; } - public bool Deployed { get; set; } - public string Message { get; set; } -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs new file mode 100644 index 0000000..e180eaf --- /dev/null +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs @@ -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 Parameters { get; set; } +} + +public class SqlQueryExecutionResultDto +{ + public bool Success { get; set; } + public string Message { get; set; } + public IEnumerable Data { get; set; } + public int RowsAffected { get; set; } + public long ExecutionTimeMs { get; set; } + public Dictionary Metadata { get; set; } +} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlFunctionDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlFunctionDto.cs deleted file mode 100644 index 8c0aa01..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlFunctionDto.cs +++ /dev/null @@ -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 -{ - 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; } -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlObjectExplorerDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlObjectExplorerDto.cs index 453dd6d..513c0ae 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlObjectExplorerDto.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlObjectExplorerDto.cs @@ -3,37 +3,23 @@ using System.Collections.Generic; namespace Sozsoft.SqlQueryManager.Application.Contracts; /// -/// Combined DTO for Object Explorer containing all SQL objects +/// A native SQL Server object (view, stored procedure, or function) discovered from system catalogs. +/// +public class SqlNativeObjectDto +{ + public string SchemaName { get; set; } = "dbo"; + public string ObjectName { get; set; } = ""; + public string FullName => $"[{SchemaName}].[{ObjectName}]"; +} + +/// +/// Object Explorer DTO - reflects the live SQL Server catalog structure. /// public class SqlObjectExplorerDto { - /// - /// SQL Queries - /// - public List Queries { get; set; } = new(); - - /// - /// Stored Procedures - /// - public List StoredProcedures { get; set; } = new(); - - /// - /// Views - /// - public List Views { get; set; } = new(); - - /// - /// Functions - /// - public List Functions { get; set; } = new(); - - /// - /// Database Tables - /// public List Tables { get; set; } = new(); - - /// - /// Query Templates - /// + public List Views { get; set; } = new(); + public List StoredProcedures { get; set; } = new(); + public List Functions { get; set; } = new(); public List Templates { get; set; } = new(); } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlQueryDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlQueryDto.cs deleted file mode 100644 index 0280be3..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlQueryDto.cs +++ /dev/null @@ -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 -{ - 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 Parameters { get; set; } -} - -public class SqlQueryExecutionResultDto -{ - public bool Success { get; set; } - public string Message { get; set; } - public IEnumerable Data { get; set; } - public int RowsAffected { get; set; } - public long ExecutionTimeMs { get; set; } - public Dictionary Metadata { get; set; } -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlStoredProcedureDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlStoredProcedureDto.cs deleted file mode 100644 index 539cfd2..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlStoredProcedureDto.cs +++ /dev/null @@ -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 -{ - 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; } -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlViewDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlViewDto.cs deleted file mode 100644 index 9cb91c3..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlViewDto.cs +++ /dev/null @@ -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 -{ - 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; } -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs index feec6ec..8d40c06 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs @@ -1,52 +1,34 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; -using System.Text; using System.Threading.Tasks; using Sozsoft.SqlQueryManager.Application.Contracts; -using Sozsoft.SqlQueryManager.Domain.Entities; using Sozsoft.SqlQueryManager.Domain.Services; -using Sozsoft.SqlQueryManager.Domain.Shared; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Volo.Abp.Application.Services; -using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; namespace Sozsoft.SqlQueryManager.Application; /// -/// Unified service for SQL Object Explorer -/// Combines all SQL objects into a single endpoint +/// Executes T-SQL against configured data sources and exposes database metadata. +/// Does not persist SQL objects (queries, procedures, views, functions) to its own tables. /// [Authorize("App.SqlQueryManager")] public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerAppService { - private readonly IRepository _queryRepository; - private readonly IRepository _procedureRepository; - private readonly IRepository _viewRepository; - private readonly IRepository _functionRepository; private readonly ISqlExecutorService _sqlExecutorService; private readonly ISqlTemplateProvider _templateProvider; private readonly ICurrentTenant _currentTenant; private readonly IHttpContextAccessor _httpContextAccessor; public SqlObjectManagerAppService( - IRepository queryRepository, - IRepository procedureRepository, - IRepository viewRepository, - IRepository functionRepository, ISqlExecutorService sqlExecutorService, ISqlTemplateProvider templateProvider, ICurrentTenant currentTenant, - IHttpContextAccessor httpContextAccessor - ) + IHttpContextAccessor httpContextAccessor) { - _queryRepository = queryRepository; - _procedureRepository = procedureRepository; - _viewRepository = viewRepository; - _functionRepository = functionRepository; _sqlExecutorService = sqlExecutorService; _templateProvider = templateProvider; _currentTenant = currentTenant; @@ -80,41 +62,11 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA ValidateTenantAccess(); var result = new SqlObjectExplorerDto(); - // Get all queries for this data source - var queries = await _queryRepository.GetListAsync(); - result.Queries = queries - .Where(q => q.DataSourceCode == dataSourceCode) - .Select(q => new SqlQueryDto - { - Id = q.Id, - Code = q.Code, - Name = q.Name, - Description = q.Description, - QueryText = q.QueryText, - DataSourceCode = q.DataSourceCode, - Status = q.Status, - Category = q.Category, - Tags = q.Tags, - IsModifyingData = q.IsModifyingData, - Parameters = q.Parameters, - ExecutionCount = q.ExecutionCount, - LastExecutedAt = q.LastExecutedAt - }) - .ToList(); - - // Get all stored procedures for this data source (custom + native merged) - result.StoredProcedures = await GetMergedStoredProceduresAsync(dataSourceCode); - - // Get all views for this data source (custom + native merged) - result.Views = await GetMergedViewsAsync(dataSourceCode); - - // Get all functions for this data source (custom + native merged) - result.Functions = await GetMergedFunctionsAsync(dataSourceCode); - - // Get all database tables result.Tables = await GetTablesAsync(dataSourceCode); + result.Views = await GetNativeObjectsAsync(dataSourceCode, "V"); + result.StoredProcedures = await GetNativeObjectsAsync(dataSourceCode, "P"); + result.Functions = await GetNativeObjectsAsync(dataSourceCode, "FN", "IF", "TF"); - // Get all templates result.Templates = _templateProvider.GetAvailableQueryTemplates() .Select(t => new SqlTemplateDto { @@ -128,6 +80,43 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA return result; } + private async Task> GetNativeObjectsAsync(string dataSourceCode, params string[] objectTypes) + { + var typeList = string.Join(",", objectTypes.Select(t => $"'{t}'")); + var query = $@" + SELECT + SCHEMA_NAME(o.schema_id) AS SchemaName, + o.name AS ObjectName + FROM + sys.objects o + WHERE + o.type IN ({typeList}) + AND o.is_ms_shipped = 0 + ORDER BY + SCHEMA_NAME(o.schema_id), o.name"; + + var result = await _sqlExecutorService.ExecuteQueryAsync(query, dataSourceCode); + + var objects = new List(); + if (result.Success && result.Data != null) + { + foreach (var row in result.Data) + { + var dict = row as IDictionary; + if (dict != null) + { + objects.Add(new SqlNativeObjectDto + { + SchemaName = dict["SchemaName"]?.ToString() ?? "dbo", + ObjectName = dict["ObjectName"]?.ToString() ?? "" + }); + } + } + } + + return objects; + } + private async Task> GetTablesAsync(string dataSourceCode) { var query = @" @@ -148,7 +137,7 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA { foreach (var row in result.Data) { - var dict = row as System.Collections.Generic.IDictionary; + var dict = row as IDictionary; if (dict != null) { tables.Add(new DatabaseTableDto @@ -163,581 +152,16 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA return tables; } - private async Task> GetMergedStoredProceduresAsync(string dataSourceCode) - { - // Get custom stored procedures from database - var customProcedures = await _procedureRepository.GetListAsync(); - var customList = customProcedures - .Where(p => p.DataSourceCode == dataSourceCode) - .Select(p => new SqlStoredProcedureDto - { - Id = p.Id, - ProcedureName = p.ProcedureName, - SchemaName = p.SchemaName, - DisplayName = $"{p.SchemaName}.{p.ProcedureName}", - Description = p.Description, - ProcedureBody = p.ProcedureBody, - DataSourceCode = p.DataSourceCode, - Category = p.Category, - Parameters = p.Parameters, - IsDeployed = p.IsDeployed, - LastDeployedAt = p.LastDeployedAt, - IsCustom = true - }) - .ToList(); - - // Get native stored procedures from SQL Server - var nativeQuery = @" - SELECT - SCHEMA_NAME(p.schema_id) AS SchemaName, - p.name AS ProcedureName, - p.create_date AS CreatedDate, - p.modify_date AS ModifiedDate - FROM - sys.procedures p - WHERE - p.is_ms_shipped = 0 - ORDER BY - SCHEMA_NAME(p.schema_id), p.name"; - - var result = await _sqlExecutorService.ExecuteQueryAsync(nativeQuery, dataSourceCode); - var nativeList = new List(); - - if (result.Success && result.Data != null) - { - foreach (var row in result.Data) - { - var dict = row as System.Collections.Generic.IDictionary; - if (dict != null) - { - var schemaName = dict["SchemaName"]?.ToString() ?? "dbo"; - var procName = dict["ProcedureName"]?.ToString() ?? ""; - - // Skip if already exists in custom list - if (!customList.Any(c => c.SchemaName == schemaName && c.ProcedureName == procName)) - { - // Generate deterministic GUID from schema and name to ensure uniqueness - var uniqueId = GenerateDeterministicGuid($"SP_{dataSourceCode}_{schemaName}_{procName}"); - - nativeList.Add(new SqlStoredProcedureDto - { - Id = uniqueId, - SchemaName = schemaName, - ProcedureName = procName, - DisplayName = $"{schemaName}.{procName}", - DataSourceCode = dataSourceCode, - IsCustom = false, - IsDeployed = true // Native objects are already deployed - }); - } - } - } - } - - // Merge and return - return customList.Concat(nativeList).ToList(); - } - - private async Task> GetMergedViewsAsync(string dataSourceCode) - { - // Get custom views from database - var customViews = await _viewRepository.GetListAsync(); - var customList = customViews - .Where(v => v.DataSourceCode == dataSourceCode) - .Select(v => new SqlViewDto - { - Id = v.Id, - ViewName = v.ViewName, - SchemaName = v.SchemaName, - DisplayName = $"{v.SchemaName}.{v.ViewName}", - Description = v.Description, - ViewDefinition = v.ViewDefinition, - DataSourceCode = v.DataSourceCode, - Category = v.Category, - WithSchemaBinding = v.WithSchemaBinding, - IsDeployed = v.IsDeployed, - LastDeployedAt = v.LastDeployedAt, - IsCustom = true - }) - .ToList(); - - // Get native views from SQL Server - var nativeQuery = @" - SELECT - SCHEMA_NAME(v.schema_id) AS SchemaName, - v.name AS ViewName, - v.create_date AS CreatedDate, - v.modify_date AS ModifiedDate - FROM - sys.views v - WHERE - v.is_ms_shipped = 0 - ORDER BY - SCHEMA_NAME(v.schema_id), v.name"; - - var result = await _sqlExecutorService.ExecuteQueryAsync(nativeQuery, dataSourceCode); - var nativeList = new List(); - - if (result.Success && result.Data != null) - { - foreach (var row in result.Data) - { - var dict = row as System.Collections.Generic.IDictionary; - if (dict != null) - { - var schemaName = dict["SchemaName"]?.ToString() ?? "dbo"; - var viewName = dict["ViewName"]?.ToString() ?? ""; - - // Skip if already exists in custom list - if (!customList.Any(c => c.SchemaName == schemaName && c.ViewName == viewName)) - { - // Generate deterministic GUID from schema and name to ensure uniqueness - var uniqueId = GenerateDeterministicGuid($"VIEW_{dataSourceCode}_{schemaName}_{viewName}"); - - nativeList.Add(new SqlViewDto - { - Id = uniqueId, - SchemaName = schemaName, - ViewName = viewName, - DisplayName = $"{schemaName}.{viewName}", - DataSourceCode = dataSourceCode, - IsCustom = false, - IsDeployed = true - }); - } - } - } - } - - return customList.Concat(nativeList).ToList(); - } - - private async Task> GetMergedFunctionsAsync(string dataSourceCode) - { - // Get custom functions from database - var customFunctions = await _functionRepository.GetListAsync(); - var customList = customFunctions - .Where(f => f.DataSourceCode == dataSourceCode) - .Select(f => new SqlFunctionDto - { - Id = f.Id, - FunctionName = f.FunctionName, - SchemaName = f.SchemaName, - DisplayName = $"[{f.SchemaName}].[{f.FunctionName}]", - Description = f.Description, - FunctionType = f.FunctionType, - FunctionBody = f.FunctionBody, - ReturnType = f.ReturnType, - DataSourceCode = f.DataSourceCode, - Category = f.Category, - Parameters = f.Parameters, - IsDeployed = f.IsDeployed, - LastDeployedAt = f.LastDeployedAt, - IsCustom = true - }) - .ToList(); - - // Get native functions from SQL Server - var nativeQuery = @" - SELECT - SCHEMA_NAME(o.schema_id) AS SchemaName, - o.name AS FunctionName, - o.create_date AS CreatedDate, - o.modify_date AS ModifiedDate, - CASE o.type - WHEN 'FN' THEN 'Scalar' - WHEN 'IF' THEN 'InlineTableValued' - WHEN 'TF' THEN 'TableValued' - ELSE 'Unknown' - END AS FunctionType - FROM - sys.objects o - WHERE - o.type IN ('FN', 'IF', 'TF') - AND o.is_ms_shipped = 0 - ORDER BY - SCHEMA_NAME(o.schema_id), o.name"; - - var result = await _sqlExecutorService.ExecuteQueryAsync(nativeQuery, dataSourceCode); - var nativeList = new List(); - - if (result.Success && result.Data != null) - { - foreach (var row in result.Data) - { - var dict = row as System.Collections.Generic.IDictionary; - if (dict != null) - { - var schemaName = dict["SchemaName"]?.ToString() ?? "dbo"; - var funcName = dict["FunctionName"]?.ToString() ?? ""; - - // Skip if already exists in custom list - if (!customList.Any(c => c.SchemaName == schemaName && c.FunctionName == funcName)) - { - var funcTypeStr = dict["FunctionType"]?.ToString() ?? "Scalar"; - var funcType = funcTypeStr == "Scalar" ? SqlFunctionType.ScalarFunction : - funcTypeStr == "InlineTableValued" ? SqlFunctionType.InlineTableValuedFunction : - SqlFunctionType.TableValuedFunction; - - // Generate deterministic GUID from schema and name to ensure uniqueness - var uniqueId = GenerateDeterministicGuid($"FUNC_{dataSourceCode}_{schemaName}_{funcName}"); - - nativeList.Add(new SqlFunctionDto - { - Id = uniqueId, - SchemaName = schemaName, - FunctionName = funcName, - DisplayName = $"{schemaName}.{funcName}", - DataSourceCode = dataSourceCode, - FunctionType = funcType, - IsCustom = false, - IsDeployed = true - }); - } - } - } - } - - return customList.Concat(nativeList).ToList(); - } - - #region Query Operations - - public async Task CreateQueryAsync(CreateSqlQueryDto input) - { - ValidateTenantAccess(); - - var query = ObjectMapper.Map(input); - query.Status = SqlQueryStatus.Draft; - - var created = await _queryRepository.InsertAsync(query, autoSave: true); - return ObjectMapper.Map(created); - } - - public async Task UpdateQueryAsync(Guid id, UpdateSqlQueryDto input) - { - ValidateTenantAccess(); - var query = await _queryRepository.GetAsync(id); - - query.Name = input.Name; - query.Description = input.Description; - query.QueryText = input.QueryText; - query.Category = input.Category; - query.Tags = input.Tags; - - var updated = await _queryRepository.UpdateAsync(query, autoSave: true); - return ObjectMapper.Map(updated); - } - - public async Task DeleteQueryAsync(Guid id) - { - ValidateTenantAccess(); - await _queryRepository.DeleteAsync(id); - } - public async Task ExecuteQueryAsync(ExecuteSqlQueryDto input) { ValidateTenantAccess(); - var sqlText = input.QueryText.Trim(); - var sqlUpper = sqlText.ToUpperInvariant(); - - // Check if this is a DDL command (CREATE/ALTER/DROP for VIEW/PROCEDURE/FUNCTION) - bool isDDLCommand = - sqlUpper.Contains("CREATE VIEW") || sqlUpper.Contains("ALTER VIEW") || - sqlUpper.Contains("CREATE PROCEDURE") || sqlUpper.Contains("CREATE PROC") || - sqlUpper.Contains("ALTER PROCEDURE") || sqlUpper.Contains("ALTER PROC") || - sqlUpper.Contains("CREATE FUNCTION") || sqlUpper.Contains("ALTER FUNCTION") || - sqlUpper.Contains("DROP VIEW") || sqlUpper.Contains("DROP PROCEDURE") || - sqlUpper.Contains("DROP PROC") || sqlUpper.Contains("DROP FUNCTION"); - - if (isDDLCommand) - { - // For DDL commands, only validate syntax without executing - try - { - // Try to parse/validate the SQL using SET PARSEONLY - var validationSql = $"SET PARSEONLY ON;\n{sqlText}\nSET PARSEONLY OFF;"; - await _sqlExecutorService.ExecuteNonQueryAsync(validationSql, input.DataSourceCode); - - return new SqlQueryExecutionResultDto - { - Success = true, - Message = "SQL syntax is valid. Use Save button to save and Deploy button to create in SQL Server.", - Data = new List(), - RowsAffected = 0, - ExecutionTimeMs = 0 - }; - } - catch (Exception ex) - { - return new SqlQueryExecutionResultDto - { - Success = false, - Message = $"SQL syntax error: {ex.Message}", - Data = new List(), - RowsAffected = 0, - ExecutionTimeMs = 0 - }; - } - } - - // For DML commands (SELECT, INSERT, UPDATE, DELETE), execute normally - var result = await _sqlExecutorService.ExecuteQueryAsync(input.QueryText, input.DataSourceCode); + var result = await _sqlExecutorService.ExecuteQueryAsync( + input.QueryText, + input.DataSourceCode, + input.Parameters); return MapExecutionResult(result); } - public async Task ExecuteSavedQueryAsync(Guid id) - { - ValidateTenantAccess(); - var query = await _queryRepository.GetAsync(id); - var result = await _sqlExecutorService.ExecuteQueryAsync(query.QueryText, query.DataSourceCode); - - // Update execution statistics - query.ExecutionCount++; - query.LastExecutedAt = DateTime.UtcNow; - await _queryRepository.UpdateAsync(query, autoSave: true); - - return MapExecutionResult(result); - } - - #endregion - - #region Stored Procedure Operations - - public async Task UpdateStoredProcedureAsync(Guid id, UpdateSqlStoredProcedureDto input) - { - ValidateTenantAccess(); - var procedure = await _procedureRepository.GetAsync(id); - - procedure.DisplayName = input.DisplayName; - procedure.Description = input.Description; - procedure.ProcedureBody = input.ProcedureBody; - procedure.Category = input.Category; - procedure.IsDeployed = false; - procedure.LastDeployedAt = null; - - var updated = await _procedureRepository.UpdateAsync(procedure, autoSave: true); - return ObjectMapper.Map(updated); - } - - public async Task DeleteStoredProcedureAsync(Guid id) - { - ValidateTenantAccess(); - var procedure = await _procedureRepository.GetAsync(id); - - // Drop stored procedure from SQL Server (always try, regardless of IsDeployed flag) - try - { - var dropSql = $"IF OBJECT_ID('[{procedure.SchemaName}].[{procedure.ProcedureName}]', 'P') IS NOT NULL DROP PROCEDURE [{procedure.SchemaName}].[{procedure.ProcedureName}]"; - await _sqlExecutorService.ExecuteNonQueryAsync(dropSql, procedure.DataSourceCode); - } - catch - { - // Ignore errors if object doesn't exist in database - } - - await _procedureRepository.DeleteAsync(id); - } - - public async Task DeployStoredProcedureAsync(DeployStoredProcedureDto input) - { - ValidateTenantAccess(); - var procedure = await _procedureRepository.GetAsync(input.Id); - - try - { - // Önce DROP işlemi yap (varsa) - var dropSql = $"IF OBJECT_ID('[{procedure.SchemaName}].[{procedure.ProcedureName}]', 'P') IS NOT NULL DROP PROCEDURE [{procedure.SchemaName}].[{procedure.ProcedureName}]"; - await _sqlExecutorService.ExecuteNonQueryAsync(dropSql, procedure.DataSourceCode); - - // Sonra CREATE işlemi yap - var result = await _sqlExecutorService.DeployStoredProcedureAsync( - procedure.ProcedureBody, - procedure.DataSourceCode - ); - - if (result.Success) - { - procedure.IsDeployed = true; - procedure.LastDeployedAt = DateTime.UtcNow; - await _procedureRepository.UpdateAsync(procedure, autoSave: true); - } - - return MapExecutionResult(result); - } - catch (Exception ex) - { - return new SqlQueryExecutionResultDto - { - Success = false, - Message = $"Deploy failed: {ex.Message}", - Data = new List(), - RowsAffected = 0, - ExecutionTimeMs = 0 - }; - } - } - - #endregion - - #region View Operations - - public async Task UpdateViewAsync(Guid id, UpdateSqlViewDto input) - { - ValidateTenantAccess(); - var view = await _viewRepository.GetAsync(id); - - view.DisplayName = input.DisplayName; - view.Description = input.Description; - view.ViewDefinition = input.ViewDefinition; - view.Category = input.Category; - view.IsDeployed = false; - view.LastDeployedAt = null; - - var updated = await _viewRepository.UpdateAsync(view, autoSave: true); - return ObjectMapper.Map(updated); - } - - public async Task DeleteViewAsync(Guid id) - { - ValidateTenantAccess(); - var view = await _viewRepository.GetAsync(id); - - // Drop view from SQL Server (always try, regardless of IsDeployed flag) - try - { - var dropSql = $"IF OBJECT_ID('[{view.SchemaName}].[{view.ViewName}]', 'V') IS NOT NULL DROP VIEW [{view.SchemaName}].[{view.ViewName}]"; - await _sqlExecutorService.ExecuteNonQueryAsync(dropSql, view.DataSourceCode); - } - catch - { - // Ignore errors if object doesn't exist in database - } - - await _viewRepository.DeleteAsync(id); - } - - public async Task DeployViewAsync(DeployViewDto input) - { - ValidateTenantAccess(); - var view = await _viewRepository.GetAsync(input.Id); - - try - { - // Önce DROP işlemi yap (varsa) - var dropSql = $"IF OBJECT_ID('[{view.SchemaName}].[{view.ViewName}]', 'V') IS NOT NULL DROP VIEW [{view.SchemaName}].[{view.ViewName}]"; - await _sqlExecutorService.ExecuteNonQueryAsync(dropSql, view.DataSourceCode); - - // Sonra CREATE işlemi yap - var result = await _sqlExecutorService.DeployViewAsync( - view.ViewDefinition, - view.DataSourceCode - ); - - if (result.Success) - { - view.IsDeployed = true; - view.LastDeployedAt = DateTime.UtcNow; - await _viewRepository.UpdateAsync(view, autoSave: true); - } - - return MapExecutionResult(result); - } - catch (Exception ex) - { - return new SqlQueryExecutionResultDto - { - Success = false, - Message = $"Deploy failed: {ex.Message}", - Data = new List(), - RowsAffected = 0, - ExecutionTimeMs = 0 - }; - } - } - - #endregion - - #region Function Operations - - public async Task UpdateFunctionAsync(Guid id, UpdateSqlFunctionDto input) - { - ValidateTenantAccess(); - var function = await _functionRepository.GetAsync(id); - - function.DisplayName = input.DisplayName; - function.Description = input.Description; - function.FunctionBody = input.FunctionBody; - function.Category = input.Category; - function.IsDeployed = false; - function.LastDeployedAt = null; - - var updated = await _functionRepository.UpdateAsync(function, autoSave: true); - return ObjectMapper.Map(updated); - } - - public async Task DeleteFunctionAsync(Guid id) - { - ValidateTenantAccess(); - var function = await _functionRepository.GetAsync(id); - - // Drop function from SQL Server (always try, regardless of IsDeployed flag) - try - { - var dropSql = $"IF OBJECT_ID('[{function.SchemaName}].[{function.FunctionName}]', 'FN') IS NOT NULL DROP FUNCTION [{function.SchemaName}].[{function.FunctionName}]"; - await _sqlExecutorService.ExecuteNonQueryAsync(dropSql, function.DataSourceCode); - } - catch - { - // Ignore errors if object doesn't exist in database - } - - await _functionRepository.DeleteAsync(id); - } - - public async Task DeployFunctionAsync(DeployFunctionDto input) - { - ValidateTenantAccess(); - var function = await _functionRepository.GetAsync(input.Id); - - try - { - // Önce DROP işlemi yap (varsa) - var dropSql = $"IF OBJECT_ID('[{function.SchemaName}].[{function.FunctionName}]', 'FN') IS NOT NULL DROP FUNCTION [{function.SchemaName}].[{function.FunctionName}]"; - await _sqlExecutorService.ExecuteNonQueryAsync(dropSql, function.DataSourceCode); - - // Sonra CREATE işlemi yap - var result = await _sqlExecutorService.DeployFunctionAsync( - function.FunctionBody, - function.DataSourceCode - ); - - if (result.Success) - { - function.IsDeployed = true; - function.LastDeployedAt = DateTime.UtcNow; - await _functionRepository.UpdateAsync(function, autoSave: true); - } - - return MapExecutionResult(result); - } - catch (Exception ex) - { - return new SqlQueryExecutionResultDto - { - Success = false, - Message = $"Deploy failed: {ex.Message}", - Data = new List(), - RowsAffected = 0, - ExecutionTimeMs = 0 - }; - } - } - - #endregion - - #region Database Metadata Operations - public async Task GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName) { ValidateTenantAccess(); @@ -746,19 +170,25 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA var fullObjectName = $"[{schemaName}].[{objectName}]"; var result = await _sqlExecutorService.ExecuteQueryAsync( - query.Replace("@ObjectName", $"'{fullObjectName}'"), - dataSourceCode - ); + query.Replace("@ObjectName", $"'{fullObjectName}'"), + dataSourceCode); if (result.Success && result.Data != null) { var dataList = result.Data.ToList(); if (dataList.Count > 0) { - var row = dataList[0] as System.Collections.Generic.IDictionary; + var row = dataList[0] as IDictionary; if (row != null && row.ContainsKey("Definition")) { - return row["Definition"]?.ToString() ?? string.Empty; + var definition = row["Definition"]?.ToString() ?? string.Empty; + // Replace first CREATE keyword with ALTER so the user edits, not recreates + definition = System.Text.RegularExpressions.Regex.Replace( + definition, + @"^\s*CREATE\s+", + "ALTER ", + System.Text.RegularExpressions.RegexOptions.IgnoreCase); + return definition; } } } @@ -792,7 +222,7 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA { foreach (var row in result.Data) { - var dict = row as System.Collections.Generic.IDictionary; + var dict = row as IDictionary; if (dict != null) { columns.Add(new DatabaseColumnDto @@ -809,236 +239,6 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA return columns; } - #endregion - - public async Task SmartSaveAsync(SmartSaveInputDto input) - { - ValidateTenantAccess(); - var result = new SmartSaveResultDto(); - var sqlText = input.SqlText.Trim(); - var sqlUpper = sqlText.ToUpperInvariant(); - - try - { - // Analyze SQL to determine object type - if (sqlUpper.Contains("CREATE VIEW") || sqlUpper.Contains("ALTER VIEW")) - { - // Extract view name - var viewName = input.Name; - var schemaName = "dbo"; - var displayName = input.Name; - - // Check if view already exists - var existingView = (await _viewRepository.GetListAsync()) - .FirstOrDefault(v => v.ViewName == viewName && v.DataSourceCode == input.DataSourceCode); - - SqlView view; - if (existingView != null) - { - // Update existing view - existingView.DisplayName = displayName; - existingView.ViewDefinition = sqlText; - existingView.IsDeployed = false; - existingView.LastDeployedAt = null; - - if (!string.IsNullOrEmpty(input.Description)) - { - existingView.Description = input.Description; - } - view = await _viewRepository.UpdateAsync(existingView, autoSave: true); - result.Message = $"View '{viewName}' updated successfully. Use Deploy button to deploy changes to SQL Server."; - } - else - { - // Create new view - view = new SqlView( - GuidGenerator.Create(), - viewName, // ViewName from SQL - schemaName, - displayName, // DisplayName from user input - sqlText, - input.DataSourceCode - ); - - if (!string.IsNullOrEmpty(input.Description)) - { - view.Description = input.Description; - } - - await _viewRepository.InsertAsync(view, autoSave: true); - result.Message = $"View '{viewName}' saved successfully. Use Deploy button to deploy to SQL Server."; - } - - result.ObjectType = "View"; - result.ObjectId = view.Id; - result.Deployed = view.IsDeployed; - } - else if (sqlUpper.Contains("CREATE PROCEDURE") || sqlUpper.Contains("CREATE PROC") || - sqlUpper.Contains("ALTER PROCEDURE") || sqlUpper.Contains("ALTER PROC")) - { - // Extract procedure name - var procName = input.Name; - var schemaName = "dbo"; - var displayName = input.Name; - - // Check if procedure already exists - var existingProcedure = (await _procedureRepository.GetListAsync()) - .FirstOrDefault(p => p.ProcedureName == procName && p.DataSourceCode == input.DataSourceCode); - - SqlStoredProcedure procedure; - if (existingProcedure != null) - { - // Update existing procedure - existingProcedure.DisplayName = displayName; - existingProcedure.ProcedureBody = sqlText; - existingProcedure.IsDeployed = false; - existingProcedure.LastDeployedAt = null; - - if (!string.IsNullOrEmpty(input.Description)) - { - existingProcedure.Description = input.Description; - } - procedure = await _procedureRepository.UpdateAsync(existingProcedure, autoSave: true); - result.Message = $"Stored Procedure '{procName}' updated successfully. Use Deploy button to deploy changes to SQL Server."; - } - else - { - // Create new procedure - procedure = new SqlStoredProcedure( - GuidGenerator.Create(), - procName, // ProcedureName from SQL - schemaName, - displayName, // DisplayName from user input - sqlText, - input.DataSourceCode - ); - - if (!string.IsNullOrEmpty(input.Description)) - { - procedure.Description = input.Description; - } - - await _procedureRepository.InsertAsync(procedure, autoSave: true); - result.Message = $"Stored Procedure '{procName}' saved successfully. Use Deploy button to deploy to SQL Server."; - } - - result.ObjectType = "StoredProcedure"; - result.ObjectId = procedure.Id; - result.Deployed = procedure.IsDeployed; - } - else if (sqlUpper.Contains("CREATE FUNCTION") || sqlUpper.Contains("ALTER FUNCTION")) - { - // Extract function name - var funcName = input.Name; - var schemaName = "dbo"; - var returnType = "NVARCHAR(MAX)"; // Default, can be extracted from SQL - var displayName = input.Name; - - // Check if function already exists - var existingFunction = (await _functionRepository.GetListAsync()) - .FirstOrDefault(f => f.FunctionName == funcName && f.DataSourceCode == input.DataSourceCode); - - SqlFunction function; - if (existingFunction != null) - { - // Update existing function - existingFunction.DisplayName = displayName; - existingFunction.FunctionBody = sqlText; - existingFunction.IsDeployed = false; - existingFunction.LastDeployedAt = null; - - if (!string.IsNullOrEmpty(input.Description)) - { - existingFunction.Description = input.Description; - } - function = await _functionRepository.UpdateAsync(existingFunction, autoSave: true); - result.Message = $"Function '{funcName}' updated successfully. Use Deploy button to deploy changes to SQL Server."; - } - else - { - // Create new function - function = new SqlFunction( - GuidGenerator.Create(), - funcName, // FunctionName from SQL - schemaName, - displayName, // DisplayName from user input - SqlFunctionType.ScalarFunction, - sqlText, - returnType, - input.DataSourceCode - ); - - if (!string.IsNullOrEmpty(input.Description)) - { - function.Description = input.Description; - } - - await _functionRepository.InsertAsync(function, autoSave: true); - result.Message = $"Function '{funcName}' saved successfully. Use Deploy button to deploy to SQL Server."; - } - - result.ObjectType = "Function"; - result.ObjectId = function.Id; - result.Deployed = function.IsDeployed; - } - else - { - // Default to Query (SELECT, INSERT, UPDATE, DELETE, etc.) - var queryName = input.Name ?? $"Query_{DateTime.Now:yyyyMMddHHmmss}"; - var queryCode = queryName.Replace(" ", "_"); - - // Check if query already exists - var existingQuery = (await _queryRepository.GetListAsync()) - .FirstOrDefault(q => q.Code == queryCode && q.DataSourceCode == input.DataSourceCode); - - SqlQuery query; - if (existingQuery != null) - { - // Update existing query - existingQuery.Name = queryName; - existingQuery.QueryText = sqlText; - if (!string.IsNullOrEmpty(input.Description)) - { - existingQuery.Description = input.Description; - } - query = await _queryRepository.UpdateAsync(existingQuery, autoSave: true); - result.Message = $"Query '{queryName}' updated successfully"; - } - else - { - // Create new query - query = new SqlQuery( - GuidGenerator.Create(), - queryCode, - queryName, - sqlText, - input.DataSourceCode - ); - - if (!string.IsNullOrEmpty(input.Description)) - { - query.Description = input.Description; - } - - await _queryRepository.InsertAsync(query, autoSave: true); - result.Message = $"Query '{queryName}' saved successfully"; - } - - result.ObjectType = "Query"; - result.ObjectId = query.Id; - result.Deployed = false; // Queries are not deployed; - } - } - catch (Exception ex) - { - throw new Volo.Abp.UserFriendlyException($"Failed to save SQL object: {ex.Message}"); - } - - return result; - } - - #region Helper Methods - private SqlQueryExecutionResultDto MapExecutionResult(SqlExecutionResult result) { return new SqlQueryExecutionResultDto @@ -1051,23 +251,4 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA Metadata = result.Metadata }; } - - #endregion - - #region Helper Methods - - /// - /// Generates a deterministic GUID from a string input using MD5 hash - /// This ensures same input always produces same GUID - /// - private static Guid GenerateDeterministicGuid(string input) - { - using (var md5 = MD5.Create()) - { - var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(input)); - return new Guid(hash); - } - } - - #endregion } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlQueryManagerAutoMapperProfile.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlQueryManagerAutoMapperProfile.cs index 3688454..eea6a87 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlQueryManagerAutoMapperProfile.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlQueryManagerAutoMapperProfile.cs @@ -1,88 +1,12 @@ using AutoMapper; -using Sozsoft.SqlQueryManager.Application.Contracts; -using Sozsoft.SqlQueryManager.Domain.Entities; -using Volo.Abp.AutoMapper; namespace Sozsoft.SqlQueryManager.Application; +// No entity-to-DTO mappings needed; SQL objects are no longer persisted in this module. public class SqlQueryManagerAutoMapperProfile : Profile { public SqlQueryManagerAutoMapperProfile() { - CreateMap(); - CreateMap() - .IgnoreFullAuditedObjectProperties() - .Ignore(x => x.Id) - .Ignore(x => x.TenantId) - .Ignore(x => x.Status) - .Ignore(x => x.LastExecutedAt) - .Ignore(x => x.ExecutionCount); - - CreateMap() - .IgnoreFullAuditedObjectProperties() - .Ignore(x => x.Id) - .Ignore(x => x.TenantId) - .Ignore(x => x.Status) - .Ignore(x => x.LastExecutedAt) - .Ignore(x => x.ExecutionCount); - - CreateMap().Ignore(x => x.IsCustom); - CreateMap() - .IgnoreFullAuditedObjectProperties() - .Ignore(x => x.Id) - .Ignore(x => x.TenantId) - .Ignore(x => x.Status) - .Ignore(x => x.IsDeployed) - .Ignore(x => x.LastDeployedAt); - - CreateMap() - .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().Ignore(x => x.IsCustom); - CreateMap() - .IgnoreFullAuditedObjectProperties() - .Ignore(x => x.Id) - .Ignore(x => x.TenantId) - .Ignore(x => x.Status) - .Ignore(x => x.IsDeployed) - .Ignore(x => x.LastDeployedAt); - CreateMap() - .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().Ignore(x => x.IsCustom); - CreateMap() - .IgnoreFullAuditedObjectProperties() - .Ignore(x => x.Id) - .Ignore(x => x.TenantId) - .Ignore(x => x.Status) - .Ignore(x => x.IsDeployed) - .Ignore(x => x.LastDeployedAt); - CreateMap() - .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); + // intentionally empty } } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlObjectType.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlObjectType.cs index 9b60427..fe90524 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlObjectType.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlObjectType.cs @@ -1,23 +1,4 @@ namespace Sozsoft.SqlQueryManager.Domain.Shared; -public enum SqlObjectType -{ - 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 -} +// SqlObjectType, SqlFunctionType and SqlQueryStatus enums removed: +// The module no longer persists SQL objects and therefore does not need these enums. diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlQueryManagerPermissions.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlQueryManagerPermissions.cs index fa6a4f1..a69141a 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlQueryManagerPermissions.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain.Shared/SqlQueryManagerPermissions.cs @@ -6,50 +6,12 @@ public static class SqlQueryManagerPermissions { public const string GroupName = "SqlQueryManager"; - public static class SqlQuery + public static class SqlExecution { - public const string Default = GroupName + ".SqlQuery"; - public const string Create = Default + ".Create"; - public const string Update = Default + ".Update"; - public const string Delete = Default + ".Delete"; + public const string Default = GroupName + ".SqlExecution"; 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() { return ReflectionHelper.GetPublicConstantsRecursively(typeof(SqlQueryManagerPermissions)); diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlFunction.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlFunction.cs deleted file mode 100644 index b406b06..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlFunction.cs +++ /dev/null @@ -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; - -/// -/// SQL Function entity for creating and managing database functions -/// -public class SqlFunction : FullAuditedEntity, IMultiTenant -{ - public Guid? TenantId { get; set; } - - /// - /// Function name in database - /// - public string FunctionName { get; set; } - - /// - /// Schema name (default: dbo) - /// - public string SchemaName { get; set; } - - /// - /// Display name - /// - public string DisplayName { get; set; } - - /// - /// Description - /// - public string Description { get; set; } - - /// - /// Function type - /// - public SqlFunctionType FunctionType { get; set; } - - /// - /// Full function definition (CREATE/ALTER) - /// - public string FunctionBody { get; set; } - - /// - /// Return type definition - /// - public string ReturnType { get; set; } - - /// - /// DataSource code - /// - public string DataSourceCode { get; set; } - - /// - /// Status - /// - public SqlQueryStatus Status { get; set; } - - /// - /// Category - /// - public string Category { get; set; } - - /// - /// Whether function exists in database - /// - public bool IsDeployed { get; set; } - - /// - /// Last deployment time - /// - public DateTime? LastDeployedAt { get; set; } - - /// - /// Parameter definitions (JSON) - /// - 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}"; -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlQuery.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlQuery.cs deleted file mode 100644 index 88c89f5..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlQuery.cs +++ /dev/null @@ -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; - -/// -/// SQL Query entity for storing and managing SQL queries -/// -public class SqlQuery : FullAuditedEntity, IMultiTenant -{ - public Guid? TenantId { get; set; } - - /// - /// Unique code for the query - /// - public string Code { get; set; } - - /// - /// Display name - /// - public string Name { get; set; } - - /// - /// Description of the query - /// - public string Description { get; set; } - - /// - /// SQL query content - /// - public string QueryText { get; set; } - - /// - /// DataSource code to use for execution - /// - public string DataSourceCode { get; set; } - - /// - /// Query status - /// - public SqlQueryStatus Status { get; set; } - - /// - /// Category for organization - /// - public string Category { get; set; } - - /// - /// Tags for filtering - /// - public string Tags { get; set; } - - /// - /// Last execution time - /// - public DateTime? LastExecutedAt { get; set; } - - /// - /// Execution count - /// - public int ExecutionCount { get; set; } - - /// - /// Whether query modifies data - /// - public bool IsModifyingData { get; set; } - - /// - /// Expected parameter definitions (JSON format) - /// - 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; - } -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlStoredProcedure.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlStoredProcedure.cs deleted file mode 100644 index 646daa6..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlStoredProcedure.cs +++ /dev/null @@ -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; - -/// -/// SQL Stored Procedure entity for creating and managing stored procedures -/// -public class SqlStoredProcedure : FullAuditedEntity, IMultiTenant -{ - public Guid? TenantId { get; set; } - - /// - /// Procedure name in database - /// - public string ProcedureName { get; set; } - - /// - /// Schema name (default: dbo) - /// - public string SchemaName { get; set; } - - /// - /// Display name - /// - public string DisplayName { get; set; } - - /// - /// Description - /// - public string Description { get; set; } - - /// - /// Full procedure definition (CREATE/ALTER) - /// - public string ProcedureBody { get; set; } - - /// - /// DataSource code - /// - public string DataSourceCode { get; set; } - - /// - /// Status - /// - public SqlQueryStatus Status { get; set; } - - /// - /// Category - /// - public string Category { get; set; } - - /// - /// Whether procedure exists in database - /// - public bool IsDeployed { get; set; } - - /// - /// Last deployment time - /// - public DateTime? LastDeployedAt { get; set; } - - /// - /// Parameter definitions (JSON) - /// - 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}"; -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlView.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlView.cs deleted file mode 100644 index 539d7db..0000000 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Entities/SqlView.cs +++ /dev/null @@ -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; - -/// -/// SQL View entity for creating and managing database views -/// -public class SqlView : FullAuditedEntity, IMultiTenant -{ - public Guid? TenantId { get; set; } - - /// - /// View name in database - /// - public string ViewName { get; set; } - - /// - /// Schema name (default: dbo) - /// - public string SchemaName { get; set; } - - /// - /// Display name - /// - public string DisplayName { get; set; } - - /// - /// Description - /// - public string Description { get; set; } - - /// - /// View definition (SELECT statement) - /// - public string ViewDefinition { get; set; } - - /// - /// DataSource code - /// - public string DataSourceCode { get; set; } - - /// - /// Status - /// - public SqlQueryStatus Status { get; set; } - - /// - /// Category - /// - public string Category { get; set; } - - /// - /// Whether view exists in database - /// - public bool IsDeployed { get; set; } - - /// - /// Last deployment time - /// - public DateTime? LastDeployedAt { get; set; } - - /// - /// Whether to use WITH SCHEMABINDING - /// - 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}"; -} diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlExecutorService.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlExecutorService.cs index ec60e41..57dbddf 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlExecutorService.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlExecutorService.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; namespace Sozsoft.SqlQueryManager.Domain.Services; @@ -22,75 +22,28 @@ public class SqlExecutionResult } /// -/// Service for executing SQL commands +/// Service for executing T-SQL commands against configured data sources. /// public interface ISqlExecutorService { - /// - /// Execute a SELECT query and return results - /// + /// Execute a SELECT query and return results. Task ExecuteQueryAsync( - string sql, - string dataSourceCode, + string sql, + string dataSourceCode, Dictionary parameters = null); - - /// - /// Execute a non-query command (INSERT, UPDATE, DELETE) - /// + + /// Execute a non-query command (INSERT, UPDATE, DELETE, DDL). Task ExecuteNonQueryAsync( - string sql, - string dataSourceCode, + string sql, + string dataSourceCode, Dictionary parameters = null); - - /// - /// Execute scalar query (returns single value) - /// + + /// Execute scalar query (returns single value). Task ExecuteScalarAsync( - string sql, - string dataSourceCode, + string sql, + string dataSourceCode, Dictionary parameters = null); - - /// - /// Deploy stored procedure to database - /// - Task DeployStoredProcedureAsync( - string procedureBody, - string dataSourceCode); - - /// - /// Deploy view to database - /// - Task DeployViewAsync( - string viewDefinition, - string dataSourceCode); - - /// - /// Deploy function to database - /// - Task DeployFunctionAsync( - string functionBody, - string dataSourceCode); - - /// - /// Check if database object exists - /// - Task CheckObjectExistsAsync( - string objectName, - string objectType, - string dataSourceCode, - string schemaName = "dbo"); - - /// - /// Drop database object - /// - Task DropObjectAsync( - string objectName, - string objectType, - string dataSourceCode, - string schemaName = "dbo"); - - /// - /// Validate SQL syntax (basic validation) - /// + + /// Validate SQL syntax (basic validation). Task<(bool IsValid, string ErrorMessage)> ValidateSqlAsync(string sql); } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlTemplateProvider.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlTemplateProvider.cs index c5de969..72febda 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlTemplateProvider.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/ISqlTemplateProvider.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Sozsoft.SqlQueryManager.Domain.Shared; namespace Sozsoft.SqlQueryManager.Domain.Services; @@ -8,29 +7,21 @@ namespace Sozsoft.SqlQueryManager.Domain.Services; /// public interface ISqlTemplateProvider { - /// - /// Get stored procedure template - /// + /// Get stored procedure template. string GetStoredProcedureTemplate(string procedureName, string schemaName = "dbo"); - - /// - /// Get view template - /// + + /// Get view template. string GetViewTemplate(string viewName, string schemaName = "dbo", bool withSchemaBinding = false); - + /// - /// Get function template - /// - string GetFunctionTemplate(string functionName, SqlFunctionType functionType, string schemaName = "dbo"); - - /// - /// Get query template with common patterns + /// Get function template. functionType: "Scalar" | "TableValued" | "InlineTableValued" /// + string GetFunctionTemplate(string functionName, string functionType = "Scalar", string schemaName = "dbo"); + + /// Get query template with common patterns. string GetQueryTemplate(string queryType); - - /// - /// Get available query template types - /// + + /// Get available query template types. List GetAvailableQueryTemplates(); } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlExecutorService.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlExecutorService.cs index 00f7f79..68ff301 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlExecutorService.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlExecutorService.cs @@ -179,81 +179,6 @@ public class SqlExecutorService : DomainService, ISqlExecutorService return result; } - public async Task DeployStoredProcedureAsync( - string procedureBody, - string dataSourceCode) - { - return await ExecuteNonQueryAsync(procedureBody, dataSourceCode); - } - - public async Task DeployViewAsync( - string viewDefinition, - string dataSourceCode) - { - return await ExecuteNonQueryAsync(viewDefinition, dataSourceCode); - } - - public async Task DeployFunctionAsync( - string functionBody, - string dataSourceCode) - { - return await ExecuteNonQueryAsync(functionBody, dataSourceCode); - } - - public async Task 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 - { - { "SchemaName", schemaName }, - { "ObjectName", objectName }, - { "ObjectType", objectType.ToUpperInvariant() } - }; - - var result = await ExecuteScalarAsync(sql, dataSourceCode, parameters); - - return result.Success && result.Metadata.ContainsKey("ScalarValue") - && Convert.ToInt32(result.Metadata["ScalarValue"]) > 0; - } - catch - { - return false; - } - } - - public async Task 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) { try @@ -285,7 +210,7 @@ public class SqlExecutorService : DomainService, ISqlExecutorService // Check for balanced parentheses var openCount = sql.Count(c => c == '('); var closeCount = sql.Count(c => c == ')'); - + if (openCount != closeCount) { return Task.FromResult((false, "Unbalanced parentheses in SQL")); @@ -299,3 +224,4 @@ public class SqlExecutorService : DomainService, ISqlExecutorService } } } + diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlTemplateProvider.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlTemplateProvider.cs index 5912de4..2255ce0 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlTemplateProvider.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Domain/Services/SqlTemplateProvider.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Text; -using Sozsoft.SqlQueryManager.Domain.Shared; using Volo.Abp.DependencyInjection; namespace Sozsoft.SqlQueryManager.Domain.Services; @@ -70,13 +69,12 @@ AS 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 { - SqlFunctionType.ScalarFunction => GetScalarFunctionTemplate(functionName, schemaName), - SqlFunctionType.TableValuedFunction => GetTableValuedFunctionTemplate(functionName, schemaName), - SqlFunctionType.InlineTableValuedFunction => GetInlineTableValuedFunctionTemplate(functionName, schemaName), + "TableValued" => GetTableValuedFunctionTemplate(functionName, schemaName), + "InlineTableValued" => GetInlineTableValuedFunctionTemplate(functionName, schemaName), _ => GetScalarFunctionTemplate(functionName, schemaName) }; } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContext.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContext.cs index 6d9c828..b874ed1 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContext.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContext.cs @@ -1,4 +1,3 @@ -using Sozsoft.SqlQueryManager.Domain.Entities; using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; @@ -8,11 +7,6 @@ namespace Sozsoft.SqlQueryManager.EntityFrameworkCore; [ConnectionStringName("Default")] public class SqlQueryManagerDbContext : AbpDbContext { - public DbSet SqlQueries { get; set; } - public DbSet SqlStoredProcedures { get; set; } - public DbSet SqlViews { get; set; } - public DbSet SqlFunctions { get; set; } - public SqlQueryManagerDbContext(DbContextOptions options) : base(options) { @@ -21,7 +15,6 @@ public class SqlQueryManagerDbContext : AbpDbContext protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); - builder.ConfigureSqlQueryManager(); } } diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContextModelCreatingExtensions.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContextModelCreatingExtensions.cs index 0b63a88..e2f22e7 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContextModelCreatingExtensions.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.EntityFrameworkCore/SqlQueryManagerDbContextModelCreatingExtensions.cs @@ -1,7 +1,5 @@ -using Sozsoft.SqlQueryManager.Domain.Entities; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Volo.Abp; -using Volo.Abp.EntityFrameworkCore.Modeling; namespace Sozsoft.SqlQueryManager.EntityFrameworkCore; @@ -10,95 +8,7 @@ public static class SqlQueryManagerDbContextModelCreatingExtensions public static void ConfigureSqlQueryManager(this ModelBuilder builder) { Check.NotNull(builder, nameof(builder)); - - // SqlQuery - builder.Entity(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(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(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(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); - }); + // SQL object entities (SqlQuery, SqlStoredProcedure, SqlView, SqlFunction) have been + // removed. The module no longer persists SQL objects to its own tables. } } diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index 64773bb..38a8fe1 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -10254,6 +10254,12 @@ "tr": "Çalıştır", "en": "Execute" }, + { + "resourceName": "Platform", + "key": "App.Platform.NewQuery", + "tr": "Yeni Sorgu", + "en": "New Query" + }, { "resourceName": "Platform", "key": "App.Platform.Save", diff --git a/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs b/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs index 09bd82b..84832f9 100644 --- a/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs +++ b/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs @@ -31,10 +31,6 @@ public enum TableNameEnum ForumPost, SqlTable, SqlTableField, - SqlView, - SqlStoredProcedure, - SqlFunction, - SqlQuery, CrudEndpoint, CustomEndpoint, CustomComponent, diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302111924_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302174517_Initial.Designer.cs similarity index 94% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302111924_Initial.Designer.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302174517_Initial.Designer.cs index e9d7457..8cc2daa 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302111924_Initial.Designer.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302174517_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Sozsoft.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20260302111924_Initial")] + [Migration("20260302174517_Initial")] partial class Initial { /// @@ -4486,409 +4486,6 @@ namespace Sozsoft.Platform.Migrations b.ToTable("Sas_H_SettingDefinition", (string)null); }); - modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlFunction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("FunctionBody") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FunctionName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("FunctionType") - .HasColumnType("int"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsDeployed") - .HasColumnType("bit"); - - b.Property("LastDeployedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("Parameters") - .HasMaxLength(4096) - .HasColumnType("nvarchar(max)"); - - b.Property("ReturnType") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("SchemaName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("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("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("ExecutionCount") - .HasColumnType("int"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsModifyingData") - .HasColumnType("bit"); - - b.Property("LastExecutedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Parameters") - .HasMaxLength(4096) - .HasColumnType("nvarchar(max)"); - - b.Property("QueryText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("Tags") - .HasMaxLength(512) - .HasColumnType("nvarchar(512)"); - - b.Property("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("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsDeployed") - .HasColumnType("bit"); - - b.Property("LastDeployedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("Parameters") - .HasMaxLength(4096) - .HasColumnType("nvarchar(max)"); - - b.Property("ProcedureBody") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ProcedureName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("SchemaName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("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("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsDeployed") - .HasColumnType("bit"); - - b.Property("LastDeployedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("SchemaName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TenantId") - .HasColumnType("uniqueidentifier") - .HasColumnName("TenantId"); - - b.Property("ViewDefinition") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ViewName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("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 => { b.Property("Id") diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302111924_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302174517_Initial.cs similarity index 93% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302111924_Initial.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302174517_Initial.cs index 393d57e..0128cbe 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302111924_Initial.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260302174517_Initial.cs @@ -986,99 +986,6 @@ namespace Sozsoft.Platform.Migrations table.PrimaryKey("PK_Adm_T_SkillType", x => x.Id); }); - migrationBuilder.CreateTable( - name: "Adm_T_SqlFunction", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - TenantId = table.Column(type: "uniqueidentifier", nullable: true), - FunctionName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - SchemaName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - Description = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), - FunctionType = table.Column(type: "int", nullable: false), - FunctionBody = table.Column(type: "nvarchar(max)", nullable: false), - ReturnType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - DataSourceCode = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Status = table.Column(type: "int", nullable: false), - Category = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - IsDeployed = table.Column(type: "bit", nullable: false), - LastDeployedAt = table.Column(type: "datetime2", nullable: true), - Parameters = table.Column(type: "nvarchar(max)", maxLength: 4096, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true), - LastModificationTime = table.Column(type: "datetime2", nullable: true), - LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), - IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), - DeleterId = table.Column(type: "uniqueidentifier", nullable: true), - DeletionTime = table.Column(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(type: "uniqueidentifier", nullable: false), - TenantId = table.Column(type: "uniqueidentifier", nullable: true), - Code = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - Description = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), - QueryText = table.Column(type: "nvarchar(max)", nullable: false), - DataSourceCode = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Status = table.Column(type: "int", nullable: false), - Category = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - Tags = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), - LastExecutedAt = table.Column(type: "datetime2", nullable: true), - ExecutionCount = table.Column(type: "int", nullable: false), - IsModifyingData = table.Column(type: "bit", nullable: false), - Parameters = table.Column(type: "nvarchar(max)", maxLength: 4096, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true), - LastModificationTime = table.Column(type: "datetime2", nullable: true), - LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), - IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), - DeleterId = table.Column(type: "uniqueidentifier", nullable: true), - DeletionTime = table.Column(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(type: "uniqueidentifier", nullable: false), - TenantId = table.Column(type: "uniqueidentifier", nullable: true), - ProcedureName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - SchemaName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - Description = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), - ProcedureBody = table.Column(type: "nvarchar(max)", nullable: false), - DataSourceCode = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Status = table.Column(type: "int", nullable: false), - Category = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - IsDeployed = table.Column(type: "bit", nullable: false), - LastDeployedAt = table.Column(type: "datetime2", nullable: true), - Parameters = table.Column(type: "nvarchar(max)", maxLength: 4096, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true), - LastModificationTime = table.Column(type: "datetime2", nullable: true), - LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), - IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), - DeleterId = table.Column(type: "uniqueidentifier", nullable: true), - DeletionTime = table.Column(type: "datetime2", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Adm_T_SqlStoredProcedure", x => x.Id); - }); - migrationBuilder.CreateTable( name: "Adm_T_SqlTable", columns: table => new @@ -1107,36 +1014,6 @@ namespace Sozsoft.Platform.Migrations table.PrimaryKey("PK_Adm_T_SqlTable", x => x.Id); }); - migrationBuilder.CreateTable( - name: "Adm_T_SqlView", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - TenantId = table.Column(type: "uniqueidentifier", nullable: true), - ViewName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - SchemaName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - Description = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), - ViewDefinition = table.Column(type: "nvarchar(max)", nullable: false), - DataSourceCode = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Status = table.Column(type: "int", nullable: false), - Category = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - IsDeployed = table.Column(type: "bit", nullable: false), - LastDeployedAt = table.Column(type: "datetime2", nullable: true), - WithSchemaBinding = table.Column(type: "bit", nullable: false), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true), - LastModificationTime = table.Column(type: "datetime2", nullable: true), - LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), - IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), - DeleterId = table.Column(type: "uniqueidentifier", nullable: true), - DeletionTime = table.Column(type: "datetime2", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Adm_T_SqlView", x => x.Id); - }); - migrationBuilder.CreateTable( name: "Adm_T_UomCategory", columns: table => new @@ -2994,96 +2871,11 @@ namespace Sozsoft.Platform.Migrations table: "Adm_T_SkillLevel", 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( name: "IX_Adm_T_SqlTableField_EntityId", table: "Adm_T_SqlTableField", 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( name: "IX_Adm_T_Uom_UomCategoryId", table: "Adm_T_Uom", @@ -3359,21 +3151,9 @@ namespace Sozsoft.Platform.Migrations migrationBuilder.DropTable( name: "Adm_T_SkillLevel"); - migrationBuilder.DropTable( - name: "Adm_T_SqlFunction"); - - migrationBuilder.DropTable( - name: "Adm_T_SqlQuery"); - - migrationBuilder.DropTable( - name: "Adm_T_SqlStoredProcedure"); - migrationBuilder.DropTable( name: "Adm_T_SqlTableField"); - migrationBuilder.DropTable( - name: "Adm_T_SqlView"); - migrationBuilder.DropTable( name: "Adm_T_Uom"); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index 443d843..09953b9 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -4483,409 +4483,6 @@ namespace Sozsoft.Platform.Migrations b.ToTable("Sas_H_SettingDefinition", (string)null); }); - modelBuilder.Entity("Sozsoft.SqlQueryManager.Domain.Entities.SqlFunction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("FunctionBody") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FunctionName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("FunctionType") - .HasColumnType("int"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsDeployed") - .HasColumnType("bit"); - - b.Property("LastDeployedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("Parameters") - .HasMaxLength(4096) - .HasColumnType("nvarchar(max)"); - - b.Property("ReturnType") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("SchemaName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("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("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("ExecutionCount") - .HasColumnType("int"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsModifyingData") - .HasColumnType("bit"); - - b.Property("LastExecutedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Parameters") - .HasMaxLength(4096) - .HasColumnType("nvarchar(max)"); - - b.Property("QueryText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("Tags") - .HasMaxLength(512) - .HasColumnType("nvarchar(512)"); - - b.Property("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("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsDeployed") - .HasColumnType("bit"); - - b.Property("LastDeployedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("Parameters") - .HasMaxLength(4096) - .HasColumnType("nvarchar(max)"); - - b.Property("ProcedureBody") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ProcedureName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("SchemaName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("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("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Category") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("CreationTime") - .HasColumnType("datetime2") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnType("uniqueidentifier") - .HasColumnName("CreatorId"); - - b.Property("DataSourceCode") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("DeleterId") - .HasColumnType("uniqueidentifier") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnType("datetime2") - .HasColumnName("DeletionTime"); - - b.Property("Description") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false) - .HasColumnName("IsDeleted"); - - b.Property("IsDeployed") - .HasColumnType("bit"); - - b.Property("LastDeployedAt") - .HasColumnType("datetime2"); - - b.Property("LastModificationTime") - .HasColumnType("datetime2") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnType("uniqueidentifier") - .HasColumnName("LastModifierId"); - - b.Property("SchemaName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TenantId") - .HasColumnType("uniqueidentifier") - .HasColumnName("TenantId"); - - b.Property("ViewDefinition") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ViewName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("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 => { b.Property("Id") diff --git a/ui/src/proxy/sql-query-manager/models.ts b/ui/src/proxy/sql-query-manager/models.ts index bbf4395..cf76063 100644 --- a/ui/src/proxy/sql-query-manager/models.ts +++ b/ui/src/proxy/sql-query-manager/models.ts @@ -1,214 +1,10 @@ -import type { FullAuditedEntityDto, PagedAndSortedResultRequestDto } from '../index' - -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 { - 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 { - 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 -} - +// SQL Execution export interface ExecuteSqlQueryDto { queryText: string dataSourceCode: string parameters?: Record } -export interface ExecuteSavedQueryDto { - id: string - parameters?: Record -} - -export interface ValidateQueryDto { - queryText: string - dataSourceCode: string -} - -// SQL Stored Procedure DTOs -export interface SqlStoredProcedureDto extends FullAuditedEntityDto { - 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 { - 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 { success: boolean message: string @@ -219,42 +15,27 @@ export interface SqlQueryExecutionResultDto { error?: string } -// Request DTOs -export interface GetSqlFunctionsInput extends PagedAndSortedResultRequestDto { - filter?: string - dataSourceCode?: string - status?: SqlQueryStatus - category?: string +// SQL Templates +export interface SqlTemplateDto { + type: string + name: string + description: string + template: string } -export interface GetSqlQueriesInput extends PagedAndSortedResultRequestDto { - 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 +// Database Metadata export interface DatabaseTableDto { schemaName: string tableName: string fullName: string } +export interface SqlNativeObjectDto { + schemaName: string + objectName: string + fullName: string +} + export interface DatabaseColumnDto { columnName: string dataType: string @@ -262,12 +43,11 @@ export interface DatabaseColumnDto { maxLength?: number } -// Unified Object Explorer Response +// Object Explorer Response — mirrors live SQL Server catalog export interface SqlObjectExplorerDto { - queries: SqlQueryDto[] - storedProcedures: SqlStoredProcedureDto[] - views: SqlViewDto[] - functions: SqlFunctionDto[] tables: DatabaseTableDto[] + views: SqlNativeObjectDto[] + storedProcedures: SqlNativeObjectDto[] + functions: SqlNativeObjectDto[] templates: SqlTemplateDto[] } diff --git a/ui/src/services/sql-query-manager.service.ts b/ui/src/services/sql-query-manager.service.ts index 8ee19a4..0f25dc9 100644 --- a/ui/src/services/sql-query-manager.service.ts +++ b/ui/src/services/sql-query-manager.service.ts @@ -1,30 +1,14 @@ -import apiService, { Config } from '@/services/api.service' +import apiService, { Config } from '@/services/api.service' import type { - SqlFunctionDto, - UpdateSqlFunctionDto, - SqlQueryDto, - UpdateSqlQueryDto, - CreateSqlQueryDto, ExecuteSqlQueryDto, - SqlStoredProcedureDto, - UpdateSqlStoredProcedureDto, - DeployStoredProcedureDto, - SqlViewDto, - UpdateSqlViewDto, - DeployViewDto, - DeployFunctionDto, SqlQueryExecutionResultDto, DatabaseColumnDto, - DatabaseTableDto, SqlObjectExplorerDto, } from '@/proxy/sql-query-manager/models' export class SqlObjectManagerService { apiName = 'Default' - /** - * Get all SQL objects for Object Explorer in a single call - */ getAllObjects = (dataSourceCode: string, config?: Partial) => apiService.fetchData( { @@ -35,36 +19,6 @@ export class SqlObjectManagerService { { apiName: this.apiName, ...config }, ) - // Query Operations - createQuery = (input: CreateSqlQueryDto, config?: Partial) => - apiService.fetchData( - { - method: 'POST', - url: '/api/app/sql-object-manager/query', - data: input, - }, - { apiName: this.apiName, ...config }, - ) - - updateQuery = (id: string, input: UpdateSqlQueryDto, config?: Partial) => - apiService.fetchData( - { - method: 'PUT', - url: `/api/app/sql-object-manager/query/${id}`, - data: input, - }, - { apiName: this.apiName, ...config }, - ) - - deleteQuery = (id: string, config?: Partial) => - apiService.fetchData( - { - method: 'DELETE', - url: `/api/app/sql-object-manager/${id}/query`, - }, - { apiName: this.apiName, ...config }, - ) - executeQuery = (input: ExecuteSqlQueryDto, config?: Partial) => apiService.fetchData( { @@ -75,106 +29,6 @@ export class SqlObjectManagerService { { apiName: this.apiName, ...config }, ) - executeSavedQuery = (id: string, config?: Partial) => - apiService.fetchData( - { - 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) => - apiService.fetchData( - { - method: 'PUT', - url: `/api/app/sql-object-manager/stored-procedure/${id}`, - data: input, - }, - { apiName: this.apiName, ...config }, - ) - - deleteStoredProcedure = (id: string, config?: Partial) => - apiService.fetchData( - { - method: 'DELETE', - url: `/api/app/sql-object-manager/${id}/stored-procedure`, - }, - { apiName: this.apiName, ...config }, - ) - - deployStoredProcedure = (input: DeployStoredProcedureDto, config?: Partial) => - apiService.fetchData( - { - 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) => - apiService.fetchData( - { - method: 'PUT', - url: `/api/app/sql-object-manager/view/${id}`, - data: input, - }, - { apiName: this.apiName, ...config }, - ) - - deleteView = (id: string, config?: Partial) => - apiService.fetchData( - { - method: 'DELETE', - url: `/api/app/sql-object-manager/${id}/view`, - }, - { apiName: this.apiName, ...config }, - ) - - deployView = (input: DeployViewDto, config?: Partial) => - apiService.fetchData( - { - 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) => - apiService.fetchData( - { - method: 'PUT', - url: `/api/app/sql-object-manager/function/${id}`, - data: input, - }, - { apiName: this.apiName, ...config }, - ) - - deleteFunction = (id: string, config?: Partial) => - apiService.fetchData( - { - method: 'DELETE', - url: `/api/app/sql-object-manager/${id}/function`, - }, - { apiName: this.apiName, ...config }, - ) - - deployFunction = (input: DeployFunctionDto, config?: Partial) => - apiService.fetchData( - { - 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) => apiService.fetchData( { @@ -194,18 +48,6 @@ export class SqlObjectManagerService { }, { 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) => - 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() diff --git a/ui/src/views/developerKit/SqlObjectExplorer.tsx b/ui/src/views/developerKit/SqlObjectExplorer.tsx index ef24e8d..a8a0a75 100644 --- a/ui/src/views/developerKit/SqlObjectExplorer.tsx +++ b/ui/src/views/developerKit/SqlObjectExplorer.tsx @@ -1,454 +1,244 @@ import { useState, useEffect } from 'react' -import { Dialog, Button, Notification, toast } from '@/components/ui' import { FaRegFolder, FaRegFolderOpen, - FaRegFileAlt, - FaCog, FaColumns, - FaCode, FaSyncAlt, - FaEdit, - FaTrash, FaTable, FaPlus, + FaEye, + FaCog, + FaCode, + FaDatabase, + FaTrash, } from 'react-icons/fa' -import type { - SqlFunctionDto, - SqlQueryDto, - SqlStoredProcedureDto, - SqlViewDto, - SqlObjectType, -} from '@/proxy/sql-query-manager/models' +import type { DatabaseTableDto, SqlNativeObjectDto } from '@/proxy/sql-query-manager/models' import { sqlObjectManagerService } from '@/services/sql-query-manager.service' import { useLocalization } from '@/utils/hooks/useLocalization' -export type SqlObject = SqlFunctionDto | SqlQueryDto | SqlStoredProcedureDto | SqlViewDto +type FolderKey = 'tables' | 'views' | 'procedures' | 'functions' interface TreeNode { id: string label: string - type: 'root' | 'folder' | 'object' | 'column' - objectType?: SqlObjectType - data?: SqlObject | any + type: 'root' | 'folder' | 'object' + folder?: FolderKey + data?: DatabaseTableDto | SqlNativeObjectDto children?: TreeNode[] - expanded?: boolean - isColumn?: boolean - parentTable?: { schemaName: string; tableName: string } } interface SqlObjectExplorerProps { dataSource: string | null - onObjectSelect: (object: SqlObject | null, objectType: SqlObjectType | null) => void - selectedObject: SqlObject | null onTemplateSelect?: (template: string, templateType: string) => void - onShowTableColumns?: (schemaName: string, tableName: string) => void + onViewDefinition?: (schemaName: string, objectName: string) => void onDesignTable?: (schemaName: string, tableName: string) => void onNewTable?: () => void refreshTrigger?: number } +const FOLDER_META: Record = { + 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 = ({ dataSource, - onObjectSelect, - selectedObject, onTemplateSelect, - onShowTableColumns, + onViewDefinition, onDesignTable, onNewTable, refreshTrigger, }: SqlObjectExplorerProps) => { const { translate } = useLocalization() const [treeData, setTreeData] = useState([]) - const [expandedNodes, setExpandedNodes] = useState>( - new Set(['root']), // Only root expanded by default - ) + const [expandedNodes, setExpandedNodes] = useState>(new Set(['root'])) const [loading, setLoading] = useState(false) const [filterText, setFilterText] = useState('') + const [dropConfirm, setDropConfirm] = useState<{ node: TreeNode } | null>(null) + const [dropping, setDropping] = useState(false) const [contextMenu, setContextMenu] = useState<{ - show: boolean - x: number - y: number - node: TreeNode | null + show: boolean; x: number; y: number; node: TreeNode | 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(() => { - if (dataSource) { - loadObjects() - } else { - setTreeData([]) - } - }, [dataSource, refreshTrigger]) // refreshTrigger değişince de yenile + if (dataSource) loadObjects() + else setTreeData([]) + }, [dataSource, refreshTrigger]) const loadObjects = async () => { if (!dataSource) return - setLoading(true) try { - // Single API call to get all objects - const response = await sqlObjectManagerService.getAllObjects(dataSource || '') - const allObjects = response.data + const { data } = await sqlObjectManagerService.getAllObjects(dataSource) - const tree: TreeNode[] = [ - { - id: 'root', - label: dataSource || 'Database', - type: 'root', - expanded: true, - children: [ - { - id: 'tables', - label: `${translate('::App.Platform.Tables')} (${allObjects.tables.length})`, - type: 'folder', - expanded: expandedNodes.has('tables'), - children: - allObjects.tables.map((t) => ({ - id: `table-${t.schemaName}-${t.tableName}`, - label: t.fullName, - type: 'object' as const, - 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', - label: `${translate('::App.Platform.Views')} (${allObjects.views.length})`, - type: 'folder', - objectType: 3, - expanded: expandedNodes.has('views'), - children: - allObjects.views.map((v) => { - const deployInfo = v.isDeployed && v.lastDeployedAt - ? ` (${new Date(v.lastDeployedAt).toLocaleString('tr-TR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })})` - : ''; - const customBadge = v.isCustom ? ' 📝' : ' 🗄️'; - return { - id: v.id!, - label: `${v.displayName || v.viewName}${customBadge}${v.isDeployed ? ' ✅' : ' ❌'}${deployInfo}`, - type: 'object' as const, - objectType: 3 as SqlObjectType, - data: v, - }; - }) || [], - }, - { - id: 'functions', - label: `${translate('::App.Platform.Functions')} (${allObjects.functions.length})`, - type: 'folder', - objectType: 4, - expanded: expandedNodes.has('functions'), - 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, - })) || [], - }, - ], - }, - ] + 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', + label: dataSource, + type: 'root', + children: [ + { + id: 'tables', + label: `Tables (${data.tables.length})`, + type: 'folder', + folder: 'tables', + children: data.tables.map((t) => ({ + id: `tables-${t.schemaName}-${t.tableName}`, + label: t.fullName ?? `[${t.schemaName}].[${t.tableName}]`, + type: 'object' as const, + folder: 'tables' as FolderKey, + data: t, + })), + }, + { + id: 'views', + label: `Views (${data.views.length})`, + type: 'folder', + folder: 'views', + children: data.views.map((v) => makeObjectNode('views', v)), + }, + { + id: 'procedures', + label: `Stored Procedures (${data.storedProcedures.length})`, + type: 'folder', + folder: 'procedures', + children: data.storedProcedures.map((p) => makeObjectNode('procedures', p)), + }, + { + id: 'functions', + label: `Functions (${data.functions.length})`, + type: 'folder', + folder: 'functions', + children: data.functions.map((f) => makeObjectNode('functions', f)), + }, + ], + }] setTreeData(tree) } catch (error: any) { - toast.push( - - {error.response?.data?.error?.message || translate('::App.Platform.FailedToLoadObjects')} - , - { placement: 'top-center' }, - ) + console.error('Failed to load objects', error) } finally { setLoading(false) } } - const loadTableColumns = async (schemaName: string, tableName: string): Promise => { - try { - const response = await sqlObjectManagerService.getTableColumns( - dataSource || '', - schemaName, - 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 toggleNode = (nodeId: string) => { + setExpandedNodes((prev) => { + const next = new Set(prev) + next.has(nodeId) ? next.delete(nodeId) : next.add(nodeId) + return next }) } - const filterTree = (nodes: TreeNode[], searchText: string): TreeNode[] => { - if (!searchText.trim()) return nodes - - const search = searchText.toLowerCase() - const filtered = nodes + const filterTree = (nodes: TreeNode[], search: string): TreeNode[] => { + if (!search.trim()) return nodes + const q = search.toLowerCase() + return nodes .map((node) => { - const matchesSearch = node.label.toLowerCase().includes(search) - const filteredChildren = node.children ? filterTree(node.children, searchText) : [] - - if (matchesSearch || filteredChildren.length > 0) { - return { - ...node, - children: filteredChildren.length > 0 ? filteredChildren : node.children, - } as TreeNode - } + const match = node.label.toLowerCase().includes(q) + const kids = node.children ? filterTree(node.children, search) : [] + if (match || kids.length > 0) + return { ...node, children: kids.length > 0 ? kids : node.children } as TreeNode return null }) - .filter((node) => node !== null) as TreeNode[] - - return filtered + .filter(Boolean) as TreeNode[] } const handleNodeClick = (node: TreeNode) => { - if (node.type === 'folder' || node.type === 'root') { - toggleNode(node.id) - } else if (node.type === 'column') { - // Column clicked - do nothing or show info - return - } else if (node.type === 'object' && node.data) { - // Check if it's a table - generate SELECT template - if (node.id.startsWith('table-') && onTemplateSelect) { - const table = node.data as any - const selectQuery = `SELECT TOP 10 * \nFROM ${table.fullName || `[${table.schemaName}].[${table.tableName}]`};` - onTemplateSelect(selectQuery, 'table-select') - } else if (node.objectType) { - onObjectSelect(node.data, node.objectType) - } + if (node.type !== 'object') { toggleNode(node.id); return } + + if (node.folder === 'tables') { + // Generate SELECT template for tables + const t = node.data as DatabaseTableDto + onTemplateSelect?.(`SELECT TOP 10 *\nFROM ${t.fullName ?? `[${t.schemaName}].[${t.tableName}]`};`, 'table-select') + } else { + // Load native object definition into editor + const obj = node.data as SqlNativeObjectDto + onViewDefinition?.(obj.schemaName, obj.objectName) } } - const handleContextMenu = (e: React.MouseEvent, node: TreeNode) => { - e.preventDefault() - - // Don't show context menu for columns - if (node.type === 'column') { - return + const buildDropSql = (node: TreeNode): string => { + if (node.folder === 'tables') { + const t = node.data as DatabaseTableDto + return `DROP TABLE ${t.fullName ?? `[${t.schemaName}].[${t.tableName}]`};` } - - setContextMenu({ - show: true, - x: e.clientX, - y: e.clientY, - node, - }) + 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}]`};` } - const handleDelete = async () => { - if (!objectToDelete || !objectToDelete.object.id) return - + const handleDrop = async () => { + if (!dropConfirm || !dataSource) return + setDropping(true) try { - const { object, type } = objectToDelete - - switch (type) { - case 1: - await sqlObjectManagerService.deleteQuery(object.id!) - 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( - - {translate('::App.Platform.ObjectDeletedSuccessfully')} - , - { placement: 'top-center' }, - ) - - setShowDeleteDialog(false) - setObjectToDelete(null) + await sqlObjectManagerService.executeQuery({ + queryText: buildDropSql(dropConfirm.node), + dataSourceCode: dataSource, + }) + setDropConfirm(null) loadObjects() - - if (selectedObject?.id === object.id) { - onObjectSelect(null, null) - } - } catch (error: any) { - toast.push( - - {error.response?.data?.error?.message || translate('::App.Platform.FailedToDeleteObject')} - , - { placement: 'top-center' }, - ) + } catch (err: any) { + console.error('Drop failed', err) + } finally { + setDropping(false) } } + const closeCtx = () => setContextMenu({ show: false, x: 0, y: 0, node: null }) + const getIcon = (node: TreeNode) => { - if (node.type === 'root') return - + if (node.type === 'root') return if (node.type === 'folder') { - const isExpanded = expandedNodes.has(node.id) - - // Tables folder - if (node.id === 'tables') - return isExpanded ? ( - - ) : ( - - ) - - if (node.objectType === 1) - return isExpanded ? ( - - ) : ( - - ) - - if (node.objectType === 2) - return isExpanded ? ( - - ) : ( - - ) - - if (node.objectType === 3) - return isExpanded ? ( - - ) : ( - - ) - - if (node.objectType === 4) - return isExpanded ? ( - - ) : ( - - ) + const open = expandedNodes.has(node.id) + const cls = FOLDER_META[node.folder!]?.color ?? 'text-blue-500' + return open + ? + : } - - if (node.type === 'object') { - if (node.objectType === 1) return - if (node.objectType === 2) return - if (node.objectType === 3) return - if (node.objectType === 4) return - } - - if (node.type === 'column') { - return - } - - return + if (node.folder === 'tables') return + if (node.folder === 'views') return + if (node.folder === 'procedures') return + if (node.folder === 'functions') return + return } const renderNode = (node: TreeNode, level = 0) => { const isExpanded = expandedNodes.has(node.id) - const isSelected = node.type === 'object' && selectedObject?.id === node.id - const isColumn = node.type === 'column' - return (
!isColumn && handleNodeClick(node)} - onContextMenu={(e) => !isColumn && handleContextMenu(e, node)} + onClick={() => handleNodeClick(node)} + onContextMenu={(e) => { e.preventDefault(); setContextMenu({ show: true, x: e.clientX, y: e.clientY, node }) }} > {getIcon(node)} - - {node.label} - + {node.label} + {node.type === 'object' && ( + + )}
- {isExpanded && node.children && ( -
{node.children.map((child) => renderNode(child, level + 1))}
+
{node.children.map((c) => renderNode(c, level + 1))}
)}
) @@ -456,227 +246,162 @@ const SqlObjectExplorer = ({ 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 ( -
- {/* Filter and Refresh Controls */} -
-
- setFilterText(e.target.value)} - className="flex-1 px-3 py-1.5 text-sm border rounded-md bg-white dark:bg-gray-700 dark:border-gray-600" - /> - -
+
+ {/* Search + refresh */} +
+ setFilterText(e.target.value)} + className="flex-1 px-3 py-1.5 text-sm border rounded-md bg-white dark:bg-gray-700 dark:border-gray-600" + /> +
- {/* Tree Content */} -
- {loading && ( -
- {translate('::App.Platform.Loading')} -
- )} - {!loading && treeData.length === 0 && ( -
- {translate('::App.Platform.NoDataSourceSelected')} -
- )} - {!loading && filteredTree.length > 0 && ( -
{filteredTree.map((node) => renderNode(node))}
- )} - {!loading && treeData.length > 0 && filteredTree.length === 0 && ( -
- {translate('::App.Platform.NoResultsFound')} -
- )} + {/* Tree */} +
+ {loading &&
{translate('::App.Platform.Loading')}
} + {!loading && treeData.length === 0 &&
{translate('::App.Platform.NoDataSourceSelected')}
} + {!loading && filteredTree.length > 0 &&
{filteredTree.map((n) => renderNode(n))}
} + {!loading && treeData.length > 0 && filteredTree.length === 0 &&
{translate('::App.Platform.NoResultsFound')}
}
+ {/* Context menu */} {contextMenu.show && ( <> +
setContextMenu({ show: false, x: 0, y: 0, node: null })} - /> -
- {contextMenu.node?.id?.startsWith('table-') && ( - + )} + + {/* NATIVE object � View Definition */} + {isNativeObj && ( + + )} + + {/* FOLDER � New ... */} + {isTablesDir && ( + + )} + {isViewsDir && ( + + )} + {isProcsDir && ( + + )} + {isFuncsDir && ( + <> + - )} + + + )} - {contextMenu.node?.type === 'object' && contextMenu.node?.objectType && contextMenu.node?.data?.isCustom && ( - <> - - - - - )} - - {contextMenu.node?.type === 'object' && contextMenu.node?.objectType && !contextMenu.node?.data?.isCustom && ( -
- {translate('::App.Platform.NativeObjectViewOnly')} -
- )} - - {contextMenu.node?.type === 'folder' && ( - <> - {/* Tables folder */} - {contextMenu.node.id === 'tables' && ( - - )} - - {/* Stored Procedures folder */} - {contextMenu.node.id === 'procedures' && ( - - )} - - {/* Views folder */} - {contextMenu.node.id === 'views' && ( - - )} - - {/* Functions folder */} - {contextMenu.node.id === 'functions' && ( - - )} - - {/* Queries folder */} - {contextMenu.node.id === 'queries' && ( - - )} - - {/* Separator */} - {contextMenu.node.id !== 'root' && ( -
- )} - - {/* Refresh — all folders */} - - - )} -
+ {/* Separator + Refresh for folders */} + {isFolderNode && ( + <> +
+ + + )} +
)} - setShowDeleteDialog(false)} - onRequestClose={() => setShowDeleteDialog(false)} - > -
{translate('::App.Platform.ConfirmDelete')}
-

{translate('::App.Platform.DeleteConfirmationMessage')}

-
- - -
-
+ {/* Drop Confirm Dialog */} + {dropConfirm && ( + <> +
!dropping && setDropConfirm(null)}> +
e.stopPropagation()}> +
+ +
Drop Object
+
+

+ The following object will be permanently dropped: +

+ + {buildDropSql(dropConfirm.node)} + +
+ + +
+
+
+ + )}
) } diff --git a/ui/src/views/developerKit/SqlObjectProperties.tsx b/ui/src/views/developerKit/SqlObjectProperties.tsx index 80bcae5..c6513b6 100644 --- a/ui/src/views/developerKit/SqlObjectProperties.tsx +++ b/ui/src/views/developerKit/SqlObjectProperties.tsx @@ -1,212 +1,21 @@ -import type { - SqlFunctionDto, - 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 +interface SqlObjectPropertiesProps { + object?: any } -const SqlObjectProperties = ({ object, type }: SqlObjectPropertiesProps) => { - const { translate } = useLocalization() - - if (!object || !type) { +const SqlObjectProperties = ({ object }: SqlObjectPropertiesProps) => { + if (!object) { return ( -
- {translate('::App.Platform.SelectAnObjectToViewProperties')} +
+ Select an object to view properties
) } - const PropertyRow = ({ label, value }: { label: string; value: any }) => ( -
-
{label}
-
{value || '-'}
-
- ) - - 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 {translate('::App.Platform.Draft')} - case 2: - return {translate('::App.Platform.Active')} - case 3: - return {translate('::App.Platform.Archived')} - default: - return {translate('::App.Platform.Unknown')} - } - } - - const renderCommonProperties = () => ( - <> - - - {object.creationTime && ( - - )} - {object.lastModificationTime && ( - - )} - - ) - - const renderQueryProperties = () => { - const query = object as SqlQueryDto - return ( - <> - - - - - - - - - - {query.lastExecutedAt && ( - - )} - {renderCommonProperties()} - - ) - } - - const renderStoredProcedureProperties = () => { - const sp = object as SqlStoredProcedureDto - return ( - <> - - - - - - - - - {sp.lastDeployedAt && ( - - )} - {renderCommonProperties()} - - ) - } - - const renderViewProperties = () => { - const view = object as SqlViewDto - return ( - <> - - - - - - - - - - {view.lastDeployedAt && ( - - )} - {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 ( - <> - - - - - - - - - - - {func.lastDeployedAt && ( - - )} - {renderCommonProperties()} - - ) - } - return ( -
-
-
{translate('::App.Platform.Properties')}
-
- -
- {type === 1 && renderQueryProperties()} - {type === 2 && renderStoredProcedureProperties()} - {type === 3 && renderViewProperties()} - {type === 4 && renderFunctionProperties()} -
+
+
+        {JSON.stringify(object, null, 2)}
+      
) } diff --git a/ui/src/views/developerKit/SqlQueryManager.tsx b/ui/src/views/developerKit/SqlQueryManager.tsx index 68478f9..6b73200 100644 --- a/ui/src/views/developerKit/SqlQueryManager.tsx +++ b/ui/src/views/developerKit/SqlQueryManager.tsx @@ -1,45 +1,31 @@ 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 AdaptableCard from '@/components/shared/AdaptableCard' import { getDataSources } from '@/services/data-source.service' import type { DataSourceDto } from '@/proxy/data-source' -import type { - SqlFunctionDto, - SqlQueryDto, - SqlStoredProcedureDto, - SqlViewDto, - SqlQueryExecutionResultDto, -} from '@/proxy/sql-query-manager/models' -import { SqlObjectType } from '@/proxy/sql-query-manager/models' +import type { SqlQueryExecutionResultDto } from '@/proxy/sql-query-manager/models' 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 { useLocalization } from '@/utils/hooks/useLocalization' import SqlObjectExplorer from './SqlObjectExplorer' import SqlEditor, { SqlEditorRef } from './SqlEditor' import SqlResultsGrid from './SqlResultsGrid' -import SqlObjectProperties from './SqlObjectProperties' import SqlTableDesignerDialog from './SqlTableDesignerDialog' import { Splitter } from '@/components/codeLayout/Splitter' import { Helmet } from 'react-helmet' import { useStoreState } from '@/store/store' import { APP_NAME } from '@/constants/app.constant' -export type SqlObject = SqlFunctionDto | SqlQueryDto | SqlStoredProcedureDto | SqlViewDto - interface SqlManagerState { dataSources: DataSourceDto[] selectedDataSource: string | null - selectedObject: SqlObject | null - selectedObjectType: SqlObjectType | null editorContent: string isExecuting: boolean executionResult: SqlQueryExecutionResultDto | null showProperties: boolean isDirty: boolean tableColumns: any | null - isSaved: boolean refreshTrigger: number } @@ -51,8 +37,6 @@ const SqlQueryManager = () => { const [state, setState] = useState({ dataSources: [], selectedDataSource: tenantName ?? null, - selectedObject: null, - selectedObjectType: null, editorContent: '', isExecuting: false, refreshTrigger: 0, @@ -60,23 +44,17 @@ const SqlQueryManager = () => { showProperties: false, isDirty: false, 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 [pendingTemplate, setPendingTemplate] = useState<{ content: string; type: string } | null>( null, ) 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(() => { loadDataSources() @@ -107,7 +85,6 @@ const SqlQueryManager = () => { setState((prev) => ({ ...prev, selectedDataSource: dataSource.code ?? null, - selectedObject: null, editorContent: '', executionResult: null, isDirty: false, @@ -124,111 +101,11 @@ const SqlQueryManager = () => { 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( - - {translate('::App.Platform.FailedToLoadDefinition')} - , - { 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( - - {translate('::App.Platform.FailedToLoadDefinition')} - , - { 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( - - {translate('::App.Platform.FailedToLoadDefinition')} - , - { 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) => { setState((prev) => ({ ...prev, editorContent: value || '', isDirty: true, - isSaved: false, })) }, []) @@ -350,69 +227,14 @@ GO`, return templates[templateType] || templates['select'] } - // SQL analiz fonksiyonu - SQL metnini analiz edip nesne türünü ve adını tespit eder - 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) => ({ - ...prev, - editorContent: templateContent, - selectedObject: null, - selectedObjectType: null, - executionResult: null, - isDirty: false, - })) - }, - [], - ) + const applyTemplate = useCallback((templateContent: string) => { + setState((prev) => ({ + ...prev, + editorContent: templateContent, + executionResult: null, + isDirty: false, + })) + }, []) const handleUseTemplateFromDialog = useCallback( (templateContent: string, templateType: string) => { @@ -464,6 +286,16 @@ GO`, setPendingTemplate(null) }, []) + const handleNewQuery = useCallback(() => { + setState((prev) => ({ + ...prev, + editorContent: '', + executionResult: null, + tableColumns: null, + isDirty: false, + })) + }, []) + const handleExecute = async () => { if (!state.selectedDataSource) { toast.push( @@ -532,246 +364,29 @@ GO`, } } - const handleSave = async () => { - if (!state.selectedDataSource) { - toast.push( - - {translate('::App.Platform.PleaseSelectDataSource')} - , - { placement: 'top-center' }, - ) - return - } - - if (!state.editorContent?.trim()) { - toast.push( - - {translate('::App.Platform.PleaseEnterContentToSave')} - , - { placement: 'top-center' }, - ) - return - } - - if (state.selectedObject && state.selectedObjectType) { - // Update existing object - open dialog with existing data - const typeMap: Record = { - [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( - - {result.data.message || translate('::App.Platform.SavedSuccessfully')} - , - { placement: 'top-center' }, - ) - } catch (error: any) { - toast.push( - - {error.response?.data?.error?.message || translate('::App.Platform.FailedToSaveQuery')} - , - { placement: 'top-center' }, - ) - } - } - - const handleDeploy = async () => { - if (!state.selectedObject || !state.selectedObjectType) { - toast.push( - - {translate('::App.Platform.PleaseSelectAnObjectToDeploy')} - , - { 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( - - {translate('::App.Platform.ThisObjectTypeCannotBeDeployed')} - , - { 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( - - {translate('::App.Platform.ObjectDeployedSuccessfully')} - , - { placement: 'top-center' }, - ) - } catch (error: any) { - toast.push( - - {error.response?.data?.error?.message || translate('::App.Platform.FailedToDeployObject')} - , - { placement: 'top-center' }, - ) - } - } - - const handleShowTableColumns = async (schemaName: string, tableName: string) => { + const handleViewDefinition = async (schemaName: string, objectName: string) => { if (!state.selectedDataSource) return - try { - const response = await sqlObjectManagerService.getTableColumns( - state.selectedDataSource || '', + const result = await sqlObjectManagerService.getNativeObjectDefinition( + state.selectedDataSource, schemaName, - tableName, + objectName, ) - - // Transform API response to match display format - 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' }, - ], - }, + if (result.data) { + const definition = result.data.replace(/\bCREATE\b/i, 'ALTER') + setState((prev) => ({ + ...prev, + editorContent: definition, + executionResult: null, + tableColumns: null, + isDirty: false, + })) } - - setState((prev) => ({ - ...prev, - tableColumns: columnsResult, - executionResult: null, // Clear query results when showing columns - })) } catch (error: any) { toast.push( - {error.response?.data?.error?.message || translate('::App.Platform.FailedToLoadColumns')} + {error.response?.data?.error?.message || + translate('::App.Platform.FailedToLoadDefinition')} , { placement: 'top-center' }, ) @@ -779,14 +394,14 @@ GO`, } return ( - + -
+
{/* Toolbar */}
@@ -813,6 +428,15 @@ GO`,
+ - -
@@ -867,26 +457,22 @@ GO`, {/* Main Content Area */}
{/* Left Panel - Object Explorer */} -
- -
-
-
- {translate('::App.Platform.ObjectExplorer')} -
-
- -
-
+
+
+
+ {translate('::App.Platform.ObjectExplorer')} +
+
+
+ +
{/* Center Panel - Editor and Results */} @@ -905,7 +491,6 @@ GO`, value={state.editorContent} onChange={handleEditorChange} onExecute={handleExecute} - onSave={handleSave} readOnly={state.isExecuting} />
@@ -958,20 +543,12 @@ GO`, value={state.editorContent} onChange={handleEditorChange} onExecute={handleExecute} - onSave={handleSave} readOnly={state.isExecuting} />
)}
- - {/* Right Panel - Properties (Optional) */} - {state.showProperties && state.selectedObject && ( -
- -
- )}
@@ -1008,85 +585,6 @@ GO`, setState((prev) => ({ ...prev, refreshTrigger: prev.refreshTrigger + 1 })) }} /> - - {/* Save Dialog */} - setShowSaveDialog(false)} - onRequestClose={() => setShowSaveDialog(false)} - > -
{translate('::App.Platform.SaveQuery')}
-
- {/* Detected Object Type */} - {saveDialogData.detectedType && ( -
-
- -
-
- {translate('::App.Platform.DetectedObjectType')} -
-
- {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')} -
- {saveDialogData.detectedName && ( -
- {translate('::App.Platform.DetectedName')}:{' '} - {saveDialogData.detectedName} -
- )} -
-
-
- )} - -
- - setSaveDialogData((prev) => ({ ...prev, name: e.target.value }))} - placeholder={saveDialogData.detectedName || translate('::App.Platform.Name')} - invalid={!saveDialogData.name.trim()} - disabled={saveDialogData.isExistingObject} - /> -
-
- - - setSaveDialogData((prev) => ({ ...prev, description: e.target.value })) - } - placeholder={translate('::App.Platform.Description')} - /> -
-
- - -
-
-
) } diff --git a/ui/src/views/developerKit/SqlTableDesignerDialog.tsx b/ui/src/views/developerKit/SqlTableDesignerDialog.tsx index e0c9b65..47e14d5 100644 --- a/ui/src/views/developerKit/SqlTableDesignerDialog.tsx +++ b/ui/src/views/developerKit/SqlTableDesignerDialog.tsx @@ -957,25 +957,27 @@ const SqlTableDesignerDialog = ({ const STEP_LABELS = ['Sütun Tasarımı', 'Entity Ayarları', 'İlişkiler', 'T-SQL Önizleme'] const renderStepIndicator = () => ( -
+
{STEP_LABELS.map((label, i) => { const isDone = i < step const isActive = i === step return ( -
-
- {isDone ? : i + 1} +
+
+
+ {isDone ? : i + 1} +
+ + {label} +
- - {label} - {i < STEP_LABELS.length - 1 && ( - +
)}
)