diff --git a/docs/en/release-notes.md b/docs/en/release-notes.md index 2799ced..6e98e33 100644 --- a/docs/en/release-notes.md +++ b/docs/en/release-notes.md @@ -4,6 +4,12 @@ English | [Português (Brasil)](../pt-BR/release-notes.md) Fifth public pre-release of PGMS. It is an alpha for evaluation with synthetic/disposable data. Build label: M1053. The binaries are built and attested by the same [release workflow](../../.github/workflows/release.yml) as the previous releases. **License change:** from this release on, original work is under Apache-2.0, with credits in `NOTICE`; releases through alpha.4 remain under MIT. +## In development (not yet released) + +These changes are on `main` and will be part of the next pre-release; the downloads below are still v0.1.0-alpha.5. + +- **Query History.** **View ▸ Query History…** (`Ctrl+Alt+H`) lists the SQL executed in query tabs, with server, database, user, start, duration, rows, result and origin (typed, Query Designer, AI, other). Repeated queries collapse into one row with the last run and the count, and expand to each execution. Filter by text, connection and period; reopen in a new query tab without executing, copy, pin or delete. It is stored only on this computer, encrypted with Windows DPAPI for the current Windows user, and never sent to a server. Retention is set in **Tools ▸ Options ▸ Query Execution ▸ Query History** (defaults: 90 days, 10,000 executions, 64 KiB of SQL per execution), and a saved connection profile can turn recording off for its server. SSMS 22.11 has no built-in equivalent. Suggested by a PGMS user. + ## What changed since v0.1.0-alpha.4 - **Database diagrams.** SSMS-style diagrams saved on the server: add tables and related tables, drag a column to create a foreign key, Arrange Tables, zoom, table views, annotations, new tables and column editing inside the diagram. Database changes are shown as a SQL script first. diff --git a/docs/en/user-guide.md b/docs/en/user-guide.md index f1c38a4..8e5b8f8 100644 --- a/docs/en/user-guide.md +++ b/docs/en/user-guide.md @@ -59,6 +59,14 @@ Choose compatible PostgreSQL tools and a new output file/directory. Custom, tar, Only run trusted SQL scripts: psql scripts may include local commands, reconnects and COMMIT. Single-transaction options cannot override those commands. Cancellation can arrive after a commit. Encrypted client keys, CR/LF in tool passwords and non-ASCII TEMP paths have documented restrictions. Keep the source backup unchanged and inspect the destination after failures. The [distribution guide](distribution.md) describes tools, permissions and package requirements. +## Query History + +**View ▸ Query History…** (`Ctrl+Alt+H`) lists the SQL executed in query tabs: `F5`/**Execute** with results to grid, text or file, SQL written by Query Designer or **Generate SQL with AI**, scripts opened by **Script as** and similar tools, and **Execute SQL** inside the Query Designer. Each execution keeps the SQL (up to 64 KiB by default; longer text is cut and marked), server, port, database, user, start time, duration, rows, result (SQLSTATE and message on errors, or canceled) and origin. SQL refused before it is sent, such as text with unbound `$1` placeholders, is not recorded. SSMS 22.11 has no built-in equivalent. + +Repeated queries are grouped: one row per distinct SQL on the same server, port and database (runs of spaces and line breaks are ignored, case is not), with the last run and the count. **+** or the right arrow lists each execution. Filter by text, connection and period. **Open in New Query** puts the SQL in a new tab, connected when PGMS already has a connection to that server and user, and never executes it. **Pin** keeps a query on top and its newest execution is never removed by the limits. + +**Privacy and storage.** Query History is stored only on this computer, in `%LOCALAPPDATA%\PGMS\history`, encrypted with Windows DPAPI for the current Windows user. It is never written to a server. SQL can hold sensitive values, such as literals or a password typed in `ALTER ROLE … PASSWORD`: anyone signed in as your Windows user can read it in PGMS. Limits and the on/off switch are in **Tools ▸ Options ▸ Query Execution ▸ Query History** (defaults: 90 days, 10,000 executions, 64 KiB per execution); **Clear History…** deletes everything. To record nothing for a server, such as production, check **Do not record query history for this server** in its saved connection profile; it applies to every connection to that host and port. Writing the history never delays or fails a query: a failure only shows a message in the status bar. + ## Save and recover Save SQL files explicitly. Background recovery stores bounded encrypted drafts and may reopen them disconnected after interruption. Review recovered tabs and use **Save As**. This is not a backup system or proof that every latest keystroke was persisted. Conflicting external file changes are refused. Close the app before backing up local state; DPAPI is tied to the Windows user. Builds earlier than M934 cannot read the newer recovery container. See [validation](validation.md) for the exact cross-version recovery tested. diff --git a/docs/pt-BR/release-notes.md b/docs/pt-BR/release-notes.md index a235807..cac004e 100644 --- a/docs/pt-BR/release-notes.md +++ b/docs/pt-BR/release-notes.md @@ -4,6 +4,12 @@ Quinta pré-release pública do PGMS. É uma alpha para avaliação com dados sintéticos ou descartáveis. Rótulo de build: M1053. Os binários são gerados e atestados pelo mesmo [workflow de release](../../.github/workflows/release.yml) das versões anteriores. **Mudança de licença:** a partir desta versão, o trabalho próprio está sob Apache-2.0, com créditos no `NOTICE`; as versões até a alpha.4 continuam sob MIT. +## Em desenvolvimento (ainda não publicado) + +Estas mudanças estão no `main` e farão parte da próxima pré-release; os downloads abaixo continuam sendo da v0.1.0-alpha.5. + +- **Histórico de consultas.** **View ▸ Query History…** (`Ctrl+Alt+H`) lista o SQL executado nas abas de consulta, com servidor, banco, usuário, início, duração, linhas, resultado e origem (digitado, Query Designer, IA, outro). Consultas repetidas viram uma linha com a última execução e a contagem, que se expande em cada execução. Filtre por texto, conexão e período; reabra numa aba nova sem executar, copie, fixe ou apague. Fica só neste computador, criptografado com DPAPI do Windows para o usuário Windows atual, e nunca é enviado ao servidor. A retenção fica em **Tools ▸ Options ▸ Query Execution ▸ Query History** (padrões: 90 dias, 10.000 execuções, 64 KiB de SQL por execução), e um perfil de conexão salvo pode desligar a gravação para o servidor dele. O SSMS 22.11 não tem equivalente nativo. Sugestão de um usuário do PGMS. + ## O que mudou desde a v0.1.0-alpha.4 - **Diagramas de banco.** Diagramas como os do SSMS, salvos no servidor: adicionar tabelas e tabelas relacionadas, arrastar uma coluna para criar chave estrangeira, Arrange Tables, zoom, modos de exibição, anotações, tabelas novas e edição de colunas dentro do diagrama. Alterações no banco aparecem antes como script SQL. diff --git a/docs/pt-BR/user-guide.md b/docs/pt-BR/user-guide.md index 6f3bad9..ecec506 100644 --- a/docs/pt-BR/user-guide.md +++ b/docs/pt-BR/user-guide.md @@ -59,6 +59,14 @@ Escolha ferramentas PostgreSQL compatíveis e arquivo/diretório de saída novo. Execute apenas scripts SQL confiáveis: scripts psql podem conter comandos locais, reconexões e COMMIT. Transação única não anula esses comandos. Cancelamento pode chegar após commit. Chaves cliente criptografadas, CR/LF nas senhas das ferramentas e TEMP não ASCII têm restrições documentadas. Preserve o backup original e confira o destino após falhas. O [guia de distribuição](distribution.md) descreve ferramentas, permissões e requisitos do pacote. +## Histórico de consultas + +**View ▸ Query History…** (`Ctrl+Alt+H`) lista o SQL executado nas abas de consulta: `F5`/**Execute** com resultados em grade, texto ou arquivo, SQL escrito pelo Query Designer ou por **Generate SQL with AI**, scripts abertos por **Script as** e ferramentas parecidas, e **Execute SQL** dentro do Query Designer. Cada execução guarda o SQL (até 64 KiB por padrão; texto maior é cortado e marcado), servidor, porta, banco, usuário, início, duração, linhas, resultado (SQLSTATE e mensagem nos erros, ou cancelada) e origem. SQL recusado antes do envio, como texto com placeholders `$1` sem valor, não é gravado. O SSMS 22.11 não tem equivalente nativo. + +Consultas repetidas são agrupadas: uma linha por SQL distinto no mesmo servidor, porta e banco (sequências de espaços e quebras de linha são ignoradas; maiúsculas e minúsculas, não), com a última execução e a contagem. **+** ou a seta para a direita lista cada execução. Filtre por texto, conexão e período. **Open in New Query** põe o SQL numa aba nova, conectada quando o PGMS já tem uma conexão com aquele servidor e usuário, e nunca o executa. **Pin** deixa a consulta no topo, e a execução mais recente dela nunca é removida pelos limites. + +**Privacidade e armazenamento.** O histórico fica só neste computador, em `%LOCALAPPDATA%\PGMS\history`, criptografado com DPAPI do Windows para o usuário Windows atual. Nunca é gravado no servidor. O SQL pode ter valores sensíveis, como literais ou uma senha digitada em `ALTER ROLE … PASSWORD`: quem entrar com o seu usuário Windows consegue lê-lo no PGMS. Limites e a chave liga/desliga ficam em **Tools ▸ Options ▸ Query Execution ▸ Query History** (padrões: 90 dias, 10.000 execuções, 64 KiB por execução); **Clear History…** apaga tudo. Para não gravar nada de um servidor, como o de produção, marque **Do not record query history for this server** no perfil de conexão salvo; vale para toda conexão àquele host e porta. A gravação nunca atrasa nem faz falhar uma consulta: uma falha só mostra uma mensagem na barra de status. + ## Salvar e recuperar Salve arquivos SQL explicitamente. Recuperação em background mantém rascunhos criptografados com limites e pode reabri-los desconectados após interrupção. Revise abas recuperadas e use **Save As**. Isso não é sistema de backup nem prova de persistência de cada última tecla. Alterações externas conflitantes no arquivo são recusadas. Feche o app antes de copiar estado local; DPAPI depende do usuário Windows. Builds anteriores a M934 não leem o contêiner de recuperação mais recente. Veja a [validação](validation.md) para a recuperação entre versões realmente testada. diff --git a/scripts/Test-Integration.ps1 b/scripts/Test-Integration.ps1 index c551166..94dc5f6 100644 --- a/scripts/Test-Integration.ps1 +++ b/scripts/Test-Integration.ps1 @@ -1,6 +1,6 @@ -param([switch]$ResultsTextOnly, [switch]$TableDesignOnly, [switch]$DiagramsOnly, [switch]$ServerTlsOnly, [switch]$SchemaContextOnly, [switch]$ReportsOnly, [switch]$SessionsOnly, [switch]$PlansOnly, [switch]$ExportOnly, [switch]$ActivityOnly, [switch]$QueryStatisticsOnly, [switch]$GlobalBackupOnly, [switch]$ColumnTypesOnly, [switch]$IndexMaintenanceOnly, [switch]$IndexExpressionsOnly, [switch]$PartitionTablesOnly, [switch]$DesktopOnly, [switch]$CascadeJournalOnly, [switch]$CascadeRoutinesOnly, [switch]$CascadeRollbackOnly, [switch]$RevokePreviewOnly, [switch]$GrantorConcurrencyOnly, [switch]$ExplicitGrantorOnly, [switch]$GrantorCatalogOnly, [switch]$DefaultProcessOnly, [switch]$DefaultDelegationOnly, [switch]$DefaultSchemasOnly, [switch]$DefaultTypesOnly, [switch]$DefaultRoutinesOnly, [switch]$DefaultSequencesOnly, [switch]$DefaultTablesOnly, [switch]$DefaultCancellationOnly, [switch]$DefaultUiOnly, [switch]$DefaultJournalOnly, [switch]$DefaultPrivilegesOnly, [switch]$RoutineBoundariesOnly, [switch]$RoutineProcessOnly, [switch]$RoutineConcurrencyOnly, [switch]$RoutinePrivilegesOnly, [string]$PostgresBin = 'C:\Program Files\PostgreSQL\17\bin', [switch]$BackupFormatsOnly, [switch]$IdentityColumnsOnly, [switch]$RestoreOwnershipOnly, [switch]$UnicodeBackupOnly, [switch]$PrivilegeJournalOnly, [switch]$MaintainPrivilegeOnly, [switch]$PrivilegeCommitOnly, [switch]$UnicodePasswordOnly, [switch]$MembershipOptionsOnly, [switch]$PrivilegeIdentityOnly, [switch]$ColumnPrivilegesOnly, [switch]$PrivilegeCancellationOnly, [switch]$EffectivePrivilegesOnly, [switch]$PrivilegeCommandsOnly, [switch]$SequencePrivilegesOnly, [switch]$CopyOnly, [switch]$AdvancedIndexesOnly, [switch]$SequencesOnly, [switch]$SequenceStateOnly, [switch]$SequenceOwnerOnly, [switch]$AccessibilityOnly, [switch]$ConnectionOnly, [switch]$StreamingOnly, [switch]$ExplorerOnly, [switch]$PropertiesOnly, [switch]$AcceptanceOnly, [ValidateRange(1024,65535)][int]$TestPort = 55439) +param([switch]$ResultsTextOnly, [switch]$TableDesignOnly, [switch]$DiagramsOnly, [switch]$ServerTlsOnly, [switch]$SchemaContextOnly, [switch]$ReportsOnly, [switch]$SessionsOnly, [switch]$PlansOnly, [switch]$ExportOnly, [switch]$ActivityOnly, [switch]$QueryStatisticsOnly, [switch]$GlobalBackupOnly, [switch]$ColumnTypesOnly, [switch]$IndexMaintenanceOnly, [switch]$IndexExpressionsOnly, [switch]$PartitionTablesOnly, [switch]$DesktopOnly, [switch]$CascadeJournalOnly, [switch]$CascadeRoutinesOnly, [switch]$CascadeRollbackOnly, [switch]$RevokePreviewOnly, [switch]$GrantorConcurrencyOnly, [switch]$ExplicitGrantorOnly, [switch]$GrantorCatalogOnly, [switch]$DefaultProcessOnly, [switch]$DefaultDelegationOnly, [switch]$DefaultSchemasOnly, [switch]$DefaultTypesOnly, [switch]$DefaultRoutinesOnly, [switch]$DefaultSequencesOnly, [switch]$DefaultTablesOnly, [switch]$DefaultCancellationOnly, [switch]$DefaultUiOnly, [switch]$DefaultJournalOnly, [switch]$DefaultPrivilegesOnly, [switch]$RoutineBoundariesOnly, [switch]$RoutineProcessOnly, [switch]$RoutineConcurrencyOnly, [switch]$RoutinePrivilegesOnly, [string]$PostgresBin = 'C:\Program Files\PostgreSQL\17\bin', [switch]$BackupFormatsOnly, [switch]$IdentityColumnsOnly, [switch]$RestoreOwnershipOnly, [switch]$UnicodeBackupOnly, [switch]$PrivilegeJournalOnly, [switch]$MaintainPrivilegeOnly, [switch]$PrivilegeCommitOnly, [switch]$UnicodePasswordOnly, [switch]$MembershipOptionsOnly, [switch]$PrivilegeIdentityOnly, [switch]$ColumnPrivilegesOnly, [switch]$PrivilegeCancellationOnly, [switch]$EffectivePrivilegesOnly, [switch]$PrivilegeCommandsOnly, [switch]$SequencePrivilegesOnly, [switch]$CopyOnly, [switch]$AdvancedIndexesOnly, [switch]$SequencesOnly, [switch]$SequenceStateOnly, [switch]$SequenceOwnerOnly, [switch]$AccessibilityOnly, [switch]$ConnectionOnly, [switch]$StreamingOnly, [switch]$ExplorerOnly, [switch]$PropertiesOnly, [switch]$AcceptanceOnly, [ValidateRange(1024,65535)][int]$TestPort = 55439, [switch]$QueryHistoryOnly) $ErrorActionPreference = 'Stop' -if ((@($ResultsTextOnly, $TableDesignOnly, $DiagramsOnly, $SessionsOnly, $PlansOnly, $ExportOnly, $ActivityOnly, $QueryStatisticsOnly, $GlobalBackupOnly, $ColumnTypesOnly, $IndexMaintenanceOnly, $IndexExpressionsOnly, $PartitionTablesOnly, $CascadeJournalOnly, $CascadeRoutinesOnly, $CascadeRollbackOnly, $RevokePreviewOnly, $GrantorConcurrencyOnly, $ExplicitGrantorOnly, $GrantorCatalogOnly, $DefaultProcessOnly, $DefaultDelegationOnly, $DefaultSchemasOnly, $DefaultTypesOnly, $DefaultRoutinesOnly, $DefaultSequencesOnly, $DefaultTablesOnly, $DefaultCancellationOnly, $DefaultUiOnly, $DefaultJournalOnly, $DefaultPrivilegesOnly, $RoutineBoundariesOnly, $RoutineProcessOnly, $RoutineConcurrencyOnly, $RoutinePrivilegesOnly, $BackupFormatsOnly, $IdentityColumnsOnly, $RestoreOwnershipOnly, $UnicodeBackupOnly, $PrivilegeJournalOnly, $MaintainPrivilegeOnly, $PrivilegeCommitOnly, $UnicodePasswordOnly, $ServerTlsOnly, $SchemaContextOnly, $MembershipOptionsOnly, $PrivilegeIdentityOnly, $ColumnPrivilegesOnly, $PrivilegeCancellationOnly, $EffectivePrivilegesOnly, $PrivilegeCommandsOnly, $SequencePrivilegesOnly, $CopyOnly, $AdvancedIndexesOnly, $SequencesOnly, $SequenceStateOnly, $SequenceOwnerOnly, $AccessibilityOnly, $ConnectionOnly, $StreamingOnly, $ExplorerOnly, $ReportsOnly, $PropertiesOnly, $AcceptanceOnly) | Where-Object { $_ }).Count -gt 1) { throw 'Choose only one focused suite.' } +if ((@($ResultsTextOnly, $TableDesignOnly, $DiagramsOnly, $SessionsOnly, $PlansOnly, $ExportOnly, $ActivityOnly, $QueryStatisticsOnly, $GlobalBackupOnly, $ColumnTypesOnly, $IndexMaintenanceOnly, $IndexExpressionsOnly, $PartitionTablesOnly, $CascadeJournalOnly, $CascadeRoutinesOnly, $CascadeRollbackOnly, $RevokePreviewOnly, $GrantorConcurrencyOnly, $ExplicitGrantorOnly, $GrantorCatalogOnly, $DefaultProcessOnly, $DefaultDelegationOnly, $DefaultSchemasOnly, $DefaultTypesOnly, $DefaultRoutinesOnly, $DefaultSequencesOnly, $DefaultTablesOnly, $DefaultCancellationOnly, $DefaultUiOnly, $DefaultJournalOnly, $DefaultPrivilegesOnly, $RoutineBoundariesOnly, $RoutineProcessOnly, $RoutineConcurrencyOnly, $RoutinePrivilegesOnly, $BackupFormatsOnly, $IdentityColumnsOnly, $RestoreOwnershipOnly, $UnicodeBackupOnly, $PrivilegeJournalOnly, $MaintainPrivilegeOnly, $PrivilegeCommitOnly, $UnicodePasswordOnly, $ServerTlsOnly, $SchemaContextOnly, $MembershipOptionsOnly, $PrivilegeIdentityOnly, $ColumnPrivilegesOnly, $PrivilegeCancellationOnly, $EffectivePrivilegesOnly, $PrivilegeCommandsOnly, $SequencePrivilegesOnly, $CopyOnly, $AdvancedIndexesOnly, $SequencesOnly, $SequenceStateOnly, $SequenceOwnerOnly, $AccessibilityOnly, $ConnectionOnly, $StreamingOnly, $ExplorerOnly, $ReportsOnly, $PropertiesOnly, $AcceptanceOnly, $QueryHistoryOnly) | Where-Object { $_ }).Count -gt 1) { throw 'Choose only one focused suite.' } if ($DesktopOnly -and ($CascadeRoutinesOnly -or $CascadeRollbackOnly -or $RevokePreviewOnly -or $GrantorConcurrencyOnly -or $ExplicitGrantorOnly -or $GrantorCatalogOnly -or $DefaultDelegationOnly -or $DefaultSchemasOnly -or $DefaultTypesOnly -or $DefaultRoutinesOnly -or $DefaultSequencesOnly -or $DefaultTablesOnly -or $DefaultPrivilegesOnly -or $RoutineConcurrencyOnly -or $PrivilegeIdentityOnly -or $AcceptanceOnly -or $UnicodeBackupOnly)) { throw 'The selected focused suite has no desktop checks.' } $projectRoot = Split-Path $PSScriptRoot -Parent $testRoot = Join-Path $projectRoot 'artifacts\postgres-test' @@ -110,7 +110,8 @@ try { if ($TableDesignOnly) { $testArgs = @("--", "--table-design") } if ($DiagramsOnly) { $testArgs = @("--", "--diagrams") } if ($ResultsTextOnly) { $testArgs = @("--", "--results-text") } - if (!$CascadeJournalOnly -and !$DefaultProcessOnly -and !$DefaultCancellationOnly -and !$DefaultUiOnly -and !$DefaultJournalOnly -and !$RoutineBoundariesOnly -and !$RoutineProcessOnly -and !$DesktopOnly -and !$PrivilegeJournalOnly -and !$CopyOnly -and !$AccessibilityOnly -and !$ConnectionOnly -and !$ExplorerOnly) { + if ($QueryHistoryOnly) { $testArgs = @("--", "--query-history") } + if (!$CascadeJournalOnly -and !$DefaultProcessOnly -and !$DefaultCancellationOnly -and !$DefaultUiOnly -and !$DefaultJournalOnly -and !$RoutineBoundariesOnly -and !$RoutineProcessOnly -and !$DesktopOnly -and !$PrivilegeJournalOnly -and !$CopyOnly -and !$AccessibilityOnly -and !$ConnectionOnly -and !$ExplorerOnly -and !$QueryHistoryOnly) { dotnet run --project tests\PGMS.IntegrationTests\PGMS.IntegrationTests.csproj -c Release @testArgs if ($LASTEXITCODE -ne 0) { throw 'Integration checks failed' } } diff --git a/src/PGMS.Desktop/ConnectionDialog.xaml b/src/PGMS.Desktop/ConnectionDialog.xaml index 17f03fb..a3e7352 100644 --- a/src/PGMS.Desktop/ConnectionDialog.xaml +++ b/src/PGMS.Desktop/ConnectionDialog.xaml @@ -24,7 +24,7 @@