using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using GB5Shared.GOP.GBQueryExecutor.Models; using GB5Shared.DTO.Framework.Login; namespace GB5Shared.GOP.GBQueryExecutor { // ============================================================ // IGBQueryExecutor — Safe User-Configured SQL Execution Service // // ALL methods enforce 6 mandatory safety rules: // 1. SELECT-only AST check — DML/DDL keywords are rejected at validate time. // 2. Read-only DB connection — infrastructure concern (DB login with SELECT-only grants, // using "GBQueryExecutorReadOnly" connection string in configuration). // 3. TenantId auto-injection — @TenantId from LoginDTO is always added to parameters. // The SQL template MUST already include AND TENANTID = @TenantId in its WHERE clause // (enforced at validation time). // 4. Parameterized binding only — no string concatenation; all values via DynamicParameters. // 5. Hard row cap — SELECT TOP (@RowCap) wraps every template at runtime. // 6. Timeout ceiling — CancellationToken from HardTimeoutMs profile caps every execution. // ============================================================ public interface IGBQueryExecutor { /// /// Validates a configured query's SQL template against all 6 safety rules. /// Marks the query as Validated in the database on success. /// Must be called before ExecuteScalarAsync/ExecuteRowAsync/ExecuteDatasetAsync. /// Task ValidateAsync( string queryCode, LoginDTO loginDTO, CancellationToken ct = default); /// /// Returns the first column of the first row (COUNT, SUM, MAX, etc.). /// Query must be validated before calling. /// Task> ExecuteScalarAsync( string queryCode, Dictionary parameters, LoginDTO loginDTO, string? callerModule = null, CancellationToken ct = default); /// /// Returns a single row as a column → value dictionary. /// Query must be validated before calling. /// Task ExecuteRowAsync( string queryCode, Dictionary parameters, LoginDTO loginDTO, string? callerModule = null, CancellationToken ct = default); /// /// Returns up to HardRowCap rows as a list of column → value dictionaries. /// Query must be validated before calling. /// Task ExecuteDatasetAsync( string queryCode, Dictionary parameters, LoginDTO loginDTO, string? callerModule = null, CancellationToken ct = default); } }