using GB5Shared.DTO.Framework.SchemaIntrospection;
using SwDAL.DTO.ClientDatabase;
using SwDAL.DTO.DbServer;
using SwDAL.Enums;
namespace SwBLL.Provisioning;
///
/// Executes SQL against a remote target database using credentials from DbServerDTO.
/// Never uses Integrated Security — always SqlConnectionStringBuilder with Username/Password.
///
public interface ITargetDbExecutor
{
/// Executes a DDL or batch script (GO-separated) against the target database. Returns rows affected.
Task ExecuteScriptAsync(string connectionString, string sql, CancellationToken ct);
/// Executes a single parameterized DML statement (INSERT/UPDATE/DELETE). Returns rows affected.
Task ExecuteDmlAsync(string connectionString, string sql,
Dictionary parameters, CancellationToken ct);
///
/// Executes a SELECT-only query. Row cap: 5000. Throws if cap exceeded or non-SELECT detected.
///
Task>> ExecuteQueryAsync(
string connectionString, string sql,
Dictionary parameters,
CancellationToken ct);
/// Builds a connection string from DbServerDTO credentials. Never Integrated Security.
/// When dbUsername/dbPassword are not supplied, falls back to the DbServer's own admin
/// credential — server.DbPassword is decrypted internally in that case (it is stored
/// encrypted in MSWDBSERVER).
string BuildConnectionString(DbServerDTO server, string databaseName, string? dbUsername = null, string? dbPassword = null);
/// Builds a connection string using the least-privilege contained-user credential
/// for the given role (Dba/App/ReadOnly), read from the Vault path recorded on
/// ClientDatabaseDTO. If no credential has been provisioned for that role (e.g. a client
/// database registered outside SqlWorkbench's own provisioner), falls back to the DbServer
/// admin credential and logs a warning.
Task BuildConnectionStringForRoleAsync(
DbServerDTO server, ClientDatabaseDTO clientDb, ClientDbLoginRole role, CancellationToken ct);
/// Builds a connection string pointed at the server's admin database (SQL Server:
/// "master") rather than a specific client database — needed for RESTORE DATABASE/CREATE
/// DATABASE/ALTER DATABASE, which must run before the target database exists or while it's
/// not the current database context.
string BuildAdminConnectionString(DbServerDTO server);
/// Introspects the schema of a remote database and returns object metadata.
Task> GetServerObjectsAsync(
string connectionString, CancellationToken ct);
/// Checks whether a database with this name already exists on the server the admin
/// connection string points at. Used before RESTORE DATABASE ... WITH REPLACE (which silently
/// overwrites an existing database of the same name) and before CREATE DATABASE, so a naming
/// collision is refused with a clear error instead of destroying or racing an existing database.
Task DatabaseExistsAsync(string adminConnectionString, string databaseName, CancellationToken ct);
/// Introspects table/column metadata for a registered client database — the schema
/// browsing step of the Analytics Catalog Wizard. dbType follows SwDAL.Enums.DbType
/// (0=SqlServer, 1=PostgreSQL, 2=MySQL, 3=Oracle); only SqlServer is implemented today.
Task> GetServerColumnsAsync(
string connectionString, byte dbType, CancellationToken ct);
/// Introspects foreign-key relationships for a registered client database — used by
/// the Analytics Catalog Wizard to suggest joins between tables. dbType follows
/// SwDAL.Enums.DbType (0=SqlServer, 1=PostgreSQL, 2=MySQL, 3=Oracle); only SqlServer is
/// implemented today.
Task> GetServerForeignKeysAsync(
string connectionString, byte dbType, CancellationToken ct);
///
/// Executes a fully self-contained, possibly multi-statement, server-assembled SQL batch
/// (e.g. SELECT ... INTO #temp; SELECT ... FROM #temp) as ONE command on ONE
/// connection, so a temp table created by an early statement in the batch remains visible to
/// a later statement in the same batch — something 's
/// per-call-fresh-connection model cannot do.
///
/// This method is for pre-validated, server-assembled SQL text built by trusted BLL code
/// (e.g. the Analytics report-execution engine) — NEVER for raw end-user-supplied SQL. It is
/// not exposed via any SL/FastEndpoint route and must never be.
///
/// The SELECT-only guard is applied to the full batch text, same as
/// . Row cap defaults to a higher internal cap
/// (InternalBatchRowCap = 100,000) than the 5,000-row SelectRowCap used by
/// , since this path is meant for full report execution rather
/// than ad-hoc exploration; callers may pass to tighten it
/// further (e.g. to honor an explicit page size).
///
Task>> ExecuteQueryBatchAsync(
string connectionString, string sql, Dictionary parameters,
int? rowCapOverride, CancellationToken ct);
}
/// Remote database object metadata (table, view, procedure, function).
public class RemoteDbObjectDTO
{
public string SchemaName { get; set; } = string.Empty;
public string ObjectName { get; set; } = string.Empty;
public string ObjectType { get; set; } = string.Empty; // TABLE, VIEW, PROCEDURE, FUNCTION
}