dbqm 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbqm-1.0.0/PKG-INFO +251 -0
- dbqm-1.0.0/README.md +233 -0
- dbqm-1.0.0/dbqm/__init__.py +1 -0
- dbqm-1.0.0/dbqm/__main__.py +4 -0
- dbqm-1.0.0/dbqm/_version.py +1 -0
- dbqm-1.0.0/dbqm/cli.py +602 -0
- dbqm-1.0.0/dbqm/core/__init__.py +0 -0
- dbqm-1.0.0/dbqm/core/audit.py +49 -0
- dbqm-1.0.0/dbqm/core/config_portability.py +115 -0
- dbqm-1.0.0/dbqm/core/constants.py +2 -0
- dbqm-1.0.0/dbqm/core/crypto.py +55 -0
- dbqm-1.0.0/dbqm/core/db_manager.py +325 -0
- dbqm-1.0.0/dbqm/core/ddl_extractor.py +921 -0
- dbqm-1.0.0/dbqm/core/ddl_mysql.py +61 -0
- dbqm-1.0.0/dbqm/core/ddl_pg.py +145 -0
- dbqm-1.0.0/dbqm/core/exporter.py +577 -0
- dbqm-1.0.0/dbqm/core/group_engine.py +172 -0
- dbqm-1.0.0/dbqm/core/history.py +137 -0
- dbqm-1.0.0/dbqm/core/html_report.py +152 -0
- dbqm-1.0.0/dbqm/core/object_browser.py +976 -0
- dbqm-1.0.0/dbqm/core/package_editor.py +136 -0
- dbqm-1.0.0/dbqm/core/paths.py +28 -0
- dbqm-1.0.0/dbqm/core/query_engine.py +375 -0
- dbqm-1.0.0/dbqm/core/table_browser.py +324 -0
- dbqm-1.0.0/dbqm/main.py +38 -0
- dbqm-1.0.0/dbqm/models/__init__.py +0 -0
- dbqm-1.0.0/dbqm/models/connection.py +81 -0
- dbqm-1.0.0/dbqm/models/group.py +72 -0
- dbqm-1.0.0/dbqm/models/query.py +114 -0
- dbqm-1.0.0/dbqm/models/settings.py +39 -0
- dbqm-1.0.0/dbqm/ui/__init__.py +0 -0
- dbqm-1.0.0/dbqm/ui/app.py +476 -0
- dbqm-1.0.0/dbqm/ui/legacy/__init__.py +1 -0
- dbqm-1.0.0/dbqm/ui/legacy/display.py +94 -0
- dbqm-1.0.0/dbqm/ui/modals/__init__.py +20 -0
- dbqm-1.0.0/dbqm/ui/modals/column_maps.py +168 -0
- dbqm-1.0.0/dbqm/ui/modals/confirm.py +78 -0
- dbqm-1.0.0/dbqm/ui/modals/connection_form.py +380 -0
- dbqm-1.0.0/dbqm/ui/modals/error.py +65 -0
- dbqm-1.0.0/dbqm/ui/modals/export_picker.py +75 -0
- dbqm-1.0.0/dbqm/ui/modals/help.py +67 -0
- dbqm-1.0.0/dbqm/ui/modals/param_input.py +160 -0
- dbqm-1.0.0/dbqm/ui/modals/text_input.py +94 -0
- dbqm-1.0.0/dbqm/ui/screens/__init__.py +0 -0
- dbqm-1.0.0/dbqm/ui/screens/adhoc.py +683 -0
- dbqm-1.0.0/dbqm/ui/screens/browser.py +1072 -0
- dbqm-1.0.0/dbqm/ui/screens/config_port.py +341 -0
- dbqm-1.0.0/dbqm/ui/screens/connections.py +360 -0
- dbqm-1.0.0/dbqm/ui/screens/ddl.py +473 -0
- dbqm-1.0.0/dbqm/ui/screens/group_exec.py +823 -0
- dbqm-1.0.0/dbqm/ui/screens/group_manage.py +727 -0
- dbqm-1.0.0/dbqm/ui/screens/history.py +271 -0
- dbqm-1.0.0/dbqm/ui/screens/package_editor.py +963 -0
- dbqm-1.0.0/dbqm/ui/screens/query_exec.py +483 -0
- dbqm-1.0.0/dbqm/ui/screens/query_manage.py +1050 -0
- dbqm-1.0.0/dbqm/ui/screens/settings.py +159 -0
- dbqm-1.0.0/dbqm/ui/theme.py +52 -0
- dbqm-1.0.0/dbqm/ui/utils.py +57 -0
- dbqm-1.0.0/dbqm/ui/widgets/__init__.py +28 -0
- dbqm-1.0.0/dbqm/ui/widgets/action_bar.py +72 -0
- dbqm-1.0.0/dbqm/ui/widgets/breadcrumb.py +64 -0
- dbqm-1.0.0/dbqm/ui/widgets/group_result.py +231 -0
- dbqm-1.0.0/dbqm/ui/widgets/progress.py +51 -0
- dbqm-1.0.0/dbqm/ui/widgets/query_list.py +204 -0
- dbqm-1.0.0/dbqm/ui/widgets/result_table.py +169 -0
- dbqm-1.0.0/dbqm/ui/widgets/sidebar.py +217 -0
- dbqm-1.0.0/dbqm/ui/widgets/sql_viewer.py +45 -0
- dbqm-1.0.0/dbqm/ui/widgets/status_bar.py +81 -0
- dbqm-1.0.0/dbqm.egg-info/PKG-INFO +251 -0
- dbqm-1.0.0/dbqm.egg-info/SOURCES.txt +75 -0
- dbqm-1.0.0/dbqm.egg-info/dependency_links.txt +1 -0
- dbqm-1.0.0/dbqm.egg-info/entry_points.txt +2 -0
- dbqm-1.0.0/dbqm.egg-info/requires.txt +12 -0
- dbqm-1.0.0/dbqm.egg-info/top_level.txt +1 -0
- dbqm-1.0.0/pyproject.toml +39 -0
- dbqm-1.0.0/setup.cfg +4 -0
- dbqm-1.0.0/tests/test_cli.py +718 -0
dbqm-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dbqm
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Multi-database interactive query tool with fullscreen TUI
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: rich>=13.0
|
|
8
|
+
Requires-Dist: textual>=0.80
|
|
9
|
+
Requires-Dist: oracledb>=2.0
|
|
10
|
+
Requires-Dist: pymssql>=2.2
|
|
11
|
+
Requires-Dist: psycopg[binary]>=3.1
|
|
12
|
+
Requires-Dist: PyMySQL>=1.1
|
|
13
|
+
Requires-Dist: cryptography>=41.0
|
|
14
|
+
Requires-Dist: sqlparse>=0.5
|
|
15
|
+
Requires-Dist: Pillow>=10.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
18
|
+
|
|
19
|
+
# DB Query Manager (dbqm)
|
|
20
|
+
|
|
21
|
+
Fullscreen terminal application for managing and executing SQL queries across multiple databases. Supports **Oracle**, **SQL Server**, **PostgreSQL**, and **MySQL**. Built with [Textual](https://textual.textualize.io/) for a modern TUI experience with sidebar navigation, keyboard shortcuts, and theme support.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Fullscreen TUI** — Fixed layout with sidebar navigation, breadcrumb, status bar, and keyboard-driven workflow
|
|
26
|
+
- **Multi-database query execution** — Run saved queries against Oracle (TNS or direct), SQL Server, PostgreSQL, and MySQL
|
|
27
|
+
- **Cross-database comparison** — Execute query groups and compare results side-by-side with match/diff/absent status
|
|
28
|
+
- **DDL extraction** — Extract CREATE statements: Oracle (DBMS_METADATA), PostgreSQL (pg_catalog), MySQL (SHOW CREATE)
|
|
29
|
+
- **Package editor** — Create and edit Oracle packages with spec/body tabs, inline compilation errors from ALL_ERRORS, and wizard mode
|
|
30
|
+
- **Object browser** — Inspect tables, views, stored routines (PostgreSQL/MySQL), and Oracle packages
|
|
31
|
+
- **Ad-hoc SQL** — Paste and execute SQL with automatic parameter detection and bind variable support
|
|
32
|
+
- **Dark/Light themes** — GitHub Dark (default) and GitHub Light, switchable in settings
|
|
33
|
+
- **Data export** — Export results as CSV, JSON, TXT, PNG, HTML reports, and SQL files
|
|
34
|
+
- **Encrypted credentials** — Passwords stored with Fernet symmetric encryption
|
|
35
|
+
- **Portable configurations** — Export/import configs as encrypted `.dbqm` bundles
|
|
36
|
+
- **Favorites & folders** — Organize queries in folders, star favorites for quick access
|
|
37
|
+
- **Paginated results** — Navigate large result sets with next/prev page controls
|
|
38
|
+
- **Execution history** — Browse recent executions with timing, row counts, and status
|
|
39
|
+
- **Error handling** — Global error modal displays details instead of crashing the app
|
|
40
|
+
- **Audit logging** — Opt-in append-only JSON log of all executions
|
|
41
|
+
|
|
42
|
+
## Requirements
|
|
43
|
+
|
|
44
|
+
- Python 3.10+
|
|
45
|
+
- Oracle Instant Client (optional, for Oracle connections only)
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git clone <repo-url>
|
|
51
|
+
cd dbqm
|
|
52
|
+
|
|
53
|
+
python -m venv venv
|
|
54
|
+
# Windows
|
|
55
|
+
venv\Scripts\activate
|
|
56
|
+
# Linux/macOS
|
|
57
|
+
source venv/bin/activate
|
|
58
|
+
|
|
59
|
+
pip install -r requirements.txt
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Interactive mode (TUI)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python -m dbqm
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
On first launch, the app prompts you to configure your first database connection and generates an encryption key (`.dbqm_key`).
|
|
71
|
+
|
|
72
|
+
### CLI mode (non-interactive)
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Execute a saved query
|
|
76
|
+
python -m dbqm run <query-name> --param1 value1
|
|
77
|
+
|
|
78
|
+
# Execute a query group
|
|
79
|
+
python -m dbqm run-group <group-name> --param1 value1
|
|
80
|
+
|
|
81
|
+
# Execute ad-hoc SQL
|
|
82
|
+
python -m dbqm sql "SELECT * FROM table" <connection>
|
|
83
|
+
|
|
84
|
+
# Test connections
|
|
85
|
+
python -m dbqm test [connection]
|
|
86
|
+
|
|
87
|
+
# List resources
|
|
88
|
+
python -m dbqm list connections|queries|groups
|
|
89
|
+
|
|
90
|
+
# Extract DDL
|
|
91
|
+
python -m dbqm ddl <object> <connection>
|
|
92
|
+
|
|
93
|
+
# Export/Import configs
|
|
94
|
+
python -m dbqm export-config
|
|
95
|
+
python -m dbqm import-config <file.dbqm>
|
|
96
|
+
|
|
97
|
+
# View history
|
|
98
|
+
python -m dbqm history
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Output format options: `--format table|json|csv` and `--export csv|json|txt`.
|
|
102
|
+
|
|
103
|
+
## Keyboard Navigation
|
|
104
|
+
|
|
105
|
+
The application is fully keyboard-driven:
|
|
106
|
+
|
|
107
|
+
| Key | Action | Context |
|
|
108
|
+
|-----|--------|---------|
|
|
109
|
+
| `↑` `↓` | Navigate items / widgets | Sidebar, lists, tables, forms |
|
|
110
|
+
| `←` `→` | Switch folder tabs | Query/group lists |
|
|
111
|
+
| `Enter` | Select / Confirm | Global |
|
|
112
|
+
| `Escape` | Go back | Global |
|
|
113
|
+
| `Ctrl+B` | Toggle sidebar | Global |
|
|
114
|
+
| `Ctrl+Q` | Quit | Global |
|
|
115
|
+
| `/` | Search / filter | Lists |
|
|
116
|
+
| `?` | Help (shortcuts) | Global |
|
|
117
|
+
| `Tab` | Next widget | Forms, settings |
|
|
118
|
+
| `V` | Vertical view | Query results |
|
|
119
|
+
| `E` | Export | Query/group results |
|
|
120
|
+
| `R` | Re-execute | Query/group results |
|
|
121
|
+
| `F` | Toggle flat/pivoted | Group results |
|
|
122
|
+
| `S` | Filter by status | Group results |
|
|
123
|
+
| `H` | HTML report | Group results |
|
|
124
|
+
| `X` | Clear history | History |
|
|
125
|
+
| `N` | New item | Connections, queries |
|
|
126
|
+
| `D` | Delete / Details | Connections, history |
|
|
127
|
+
| `C` | Compile Spec | Package editor |
|
|
128
|
+
| `B` | Compile Body | Package editor |
|
|
129
|
+
|
|
130
|
+
## Sidebar
|
|
131
|
+
|
|
132
|
+
| Section | Options |
|
|
133
|
+
|---------|---------|
|
|
134
|
+
| **Consultas** | Executar, SQL avulso, Gerenciar |
|
|
135
|
+
| **Grupos** | Executar, Gerenciar |
|
|
136
|
+
| **Ferramentas** | DDL, Packages, Objetos, Historico |
|
|
137
|
+
| **Sistema** | Conexoes, Config (inclui Exportar/Importar), Sair |
|
|
138
|
+
|
|
139
|
+
## Query Groups & Comparison
|
|
140
|
+
|
|
141
|
+
Groups run the same logical query across multiple databases and compare results:
|
|
142
|
+
|
|
143
|
+
- Define a **join key** (row identifier) and **comparison columns**
|
|
144
|
+
- Optional **normalization mapping** for semantic equivalence (e.g., "paga" = "pago")
|
|
145
|
+
- Optional **column mapping** for mismatched column names
|
|
146
|
+
- Results show status per row: `OK`, `DIFF`, `ABSENT`
|
|
147
|
+
- Two display modes: **flat** (one table per column) and **pivoted** (one table per key)
|
|
148
|
+
- Filter results by status (divergent, absent, or combined)
|
|
149
|
+
- Export as HTML report with interactive filters
|
|
150
|
+
|
|
151
|
+
## Project Structure
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
dbqm/
|
|
155
|
+
├── main.py # Entry point
|
|
156
|
+
├── requirements.txt # Dependencies
|
|
157
|
+
├── dbqm/
|
|
158
|
+
│ ├── __main__.py # python -m dbqm support
|
|
159
|
+
│ ├── cli.py # Non-interactive CLI
|
|
160
|
+
│ ├── ui/
|
|
161
|
+
│ │ ├── app.py # Main Textual App (layout, routing, keybindings)
|
|
162
|
+
│ │ ├── theme.py # GitHub Dark/Light theme definitions
|
|
163
|
+
│ │ ├── utils.py # sanitize_id, escape_markup utilities
|
|
164
|
+
│ │ ├── screens/ # Screen widgets (one per feature)
|
|
165
|
+
│ │ │ ├── query_exec.py # Execute saved query
|
|
166
|
+
│ │ │ ├── query_manage.py # Query CRUD, DE-PARA, SQL viewer
|
|
167
|
+
│ │ │ ├── group_exec.py # Execute group comparison
|
|
168
|
+
│ │ │ ├── group_manage.py # Group CRUD
|
|
169
|
+
│ │ │ ├── adhoc.py # Ad-hoc SQL execution
|
|
170
|
+
│ │ │ ├── ddl.py # DDL extraction
|
|
171
|
+
│ │ │ ├── browser.py # Object browser (tables, views, packages)
|
|
172
|
+
│ │ │ ├── history.py # Execution history
|
|
173
|
+
│ │ │ ├── connections.py # Connection management
|
|
174
|
+
│ │ │ ├── package_editor.py # Oracle package editor (spec/body, compile)
|
|
175
|
+
│ │ │ ├── settings.py # Theme, audit toggle, export/import
|
|
176
|
+
│ │ │ └── config_port.py # Config export/import (used by settings)
|
|
177
|
+
│ │ ├── widgets/ # Reusable UI components
|
|
178
|
+
│ │ │ ├── sidebar.py # Collapsible sidebar with keyboard nav
|
|
179
|
+
│ │ │ ├── breadcrumb.py # Navigation breadcrumb
|
|
180
|
+
│ │ │ ├── result_table.py # DataTable with pagination + vertical view
|
|
181
|
+
│ │ │ ├── query_list.py # Query ListView with search/filter
|
|
182
|
+
│ │ │ ├── group_result.py # Flat/pivoted comparison display
|
|
183
|
+
│ │ │ ├── sql_viewer.py # Syntax-highlighted SQL display
|
|
184
|
+
│ │ │ ├── action_bar.py # Contextual keyboard shortcuts bar
|
|
185
|
+
│ │ │ ├── status_bar.py # Connection status + counters
|
|
186
|
+
│ │ │ └── progress.py # Loading indicator
|
|
187
|
+
│ │ ├── modals/ # Dialog screens
|
|
188
|
+
│ │ │ ├── param_input.py # Query parameter input
|
|
189
|
+
│ │ │ ├── confirm.py # Yes/No confirmation
|
|
190
|
+
│ │ │ ├── text_input.py # Single text input
|
|
191
|
+
│ │ │ ├── export_picker.py # Export format selector
|
|
192
|
+
│ │ │ ├── connection_form.py # Connection create/edit form
|
|
193
|
+
│ │ │ ├── column_maps.py # DE-PARA value mapping
|
|
194
|
+
│ │ │ ├── error.py # Error display modal
|
|
195
|
+
│ │ │ └── help.py # Keyboard shortcuts overlay
|
|
196
|
+
│ │ └── legacy/
|
|
197
|
+
│ │ └── display.py # Rich renderables for PNG/TXT export
|
|
198
|
+
│ ├── core/ # Business logic (database-agnostic)
|
|
199
|
+
│ │ ├── db_manager.py # Connection handling
|
|
200
|
+
│ │ ├── query_engine.py # SQL execution + parameter binding
|
|
201
|
+
│ │ ├── group_engine.py # Multi-database comparison
|
|
202
|
+
│ │ ├── exporter.py # Export (CSV, JSON, TXT, PNG)
|
|
203
|
+
│ │ ├── html_report.py # HTML comparison reports
|
|
204
|
+
│ │ ├── ddl_extractor.py # Oracle DDL (DBMS_METADATA)
|
|
205
|
+
│ │ ├── ddl_pg.py # PostgreSQL DDL
|
|
206
|
+
│ │ ├── ddl_mysql.py # MySQL DDL
|
|
207
|
+
│ │ ├── object_browser.py # Database object introspection
|
|
208
|
+
│ │ ├── table_browser.py # Table data browsing
|
|
209
|
+
│ │ ├── package_editor.py # Oracle package compile + errors
|
|
210
|
+
│ │ ├── crypto.py # Password encryption
|
|
211
|
+
│ │ ├── config_portability.py # Config import/export
|
|
212
|
+
│ │ ├── history.py # Execution history
|
|
213
|
+
│ │ └── audit.py # Audit logging
|
|
214
|
+
│ └── models/ # Data models (JSON persistence)
|
|
215
|
+
│ ├── connection.py # Connection config
|
|
216
|
+
│ ├── query.py # Query definition
|
|
217
|
+
│ ├── group.py # Query group config
|
|
218
|
+
│ └── settings.py # App settings (theme, audit)
|
|
219
|
+
├── config/ # JSON configs (gitignored)
|
|
220
|
+
├── exports/ # Generated output files (gitignored)
|
|
221
|
+
└── tests/ # Test suite (440+ tests)
|
|
222
|
+
├── core/ # Core logic tests
|
|
223
|
+
├── models/ # Model tests
|
|
224
|
+
└── ui/ # TUI widget/screen/modal tests
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Key Dependencies
|
|
228
|
+
|
|
229
|
+
| Library | Purpose |
|
|
230
|
+
|---------|---------|
|
|
231
|
+
| `textual` | Fullscreen TUI framework (layout, widgets, themes) |
|
|
232
|
+
| `rich` | Terminal formatting (used by Textual internally + exports) |
|
|
233
|
+
| `oracledb` | Oracle database driver |
|
|
234
|
+
| `pymssql` | SQL Server database driver |
|
|
235
|
+
| `psycopg` | PostgreSQL database driver (v3) |
|
|
236
|
+
| `PyMySQL` | MySQL database driver |
|
|
237
|
+
| `cryptography` | Fernet encryption for credentials |
|
|
238
|
+
| `sqlparse` | SQL analysis and classification |
|
|
239
|
+
| `Pillow` | PNG screenshot export |
|
|
240
|
+
|
|
241
|
+
## Security
|
|
242
|
+
|
|
243
|
+
- Database passwords encrypted at rest using Fernet (`.dbqm_key` master key)
|
|
244
|
+
- Configuration bundles use PBKDF2 (480,000 iterations) + Fernet
|
|
245
|
+
- Queries use bind variables to prevent SQL injection
|
|
246
|
+
- SQL identifiers validated against allowlist pattern
|
|
247
|
+
- Query results capped at 10,000 rows
|
|
248
|
+
- Config bundle imports limited to 10 MB
|
|
249
|
+
- HTML reports escape all user-controlled values
|
|
250
|
+
- Audit log files created with restricted permissions
|
|
251
|
+
- File open operations restricted to exports directory
|
dbqm-1.0.0/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# DB Query Manager (dbqm)
|
|
2
|
+
|
|
3
|
+
Fullscreen terminal application for managing and executing SQL queries across multiple databases. Supports **Oracle**, **SQL Server**, **PostgreSQL**, and **MySQL**. Built with [Textual](https://textual.textualize.io/) for a modern TUI experience with sidebar navigation, keyboard shortcuts, and theme support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Fullscreen TUI** — Fixed layout with sidebar navigation, breadcrumb, status bar, and keyboard-driven workflow
|
|
8
|
+
- **Multi-database query execution** — Run saved queries against Oracle (TNS or direct), SQL Server, PostgreSQL, and MySQL
|
|
9
|
+
- **Cross-database comparison** — Execute query groups and compare results side-by-side with match/diff/absent status
|
|
10
|
+
- **DDL extraction** — Extract CREATE statements: Oracle (DBMS_METADATA), PostgreSQL (pg_catalog), MySQL (SHOW CREATE)
|
|
11
|
+
- **Package editor** — Create and edit Oracle packages with spec/body tabs, inline compilation errors from ALL_ERRORS, and wizard mode
|
|
12
|
+
- **Object browser** — Inspect tables, views, stored routines (PostgreSQL/MySQL), and Oracle packages
|
|
13
|
+
- **Ad-hoc SQL** — Paste and execute SQL with automatic parameter detection and bind variable support
|
|
14
|
+
- **Dark/Light themes** — GitHub Dark (default) and GitHub Light, switchable in settings
|
|
15
|
+
- **Data export** — Export results as CSV, JSON, TXT, PNG, HTML reports, and SQL files
|
|
16
|
+
- **Encrypted credentials** — Passwords stored with Fernet symmetric encryption
|
|
17
|
+
- **Portable configurations** — Export/import configs as encrypted `.dbqm` bundles
|
|
18
|
+
- **Favorites & folders** — Organize queries in folders, star favorites for quick access
|
|
19
|
+
- **Paginated results** — Navigate large result sets with next/prev page controls
|
|
20
|
+
- **Execution history** — Browse recent executions with timing, row counts, and status
|
|
21
|
+
- **Error handling** — Global error modal displays details instead of crashing the app
|
|
22
|
+
- **Audit logging** — Opt-in append-only JSON log of all executions
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- Python 3.10+
|
|
27
|
+
- Oracle Instant Client (optional, for Oracle connections only)
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone <repo-url>
|
|
33
|
+
cd dbqm
|
|
34
|
+
|
|
35
|
+
python -m venv venv
|
|
36
|
+
# Windows
|
|
37
|
+
venv\Scripts\activate
|
|
38
|
+
# Linux/macOS
|
|
39
|
+
source venv/bin/activate
|
|
40
|
+
|
|
41
|
+
pip install -r requirements.txt
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
### Interactive mode (TUI)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python -m dbqm
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
On first launch, the app prompts you to configure your first database connection and generates an encryption key (`.dbqm_key`).
|
|
53
|
+
|
|
54
|
+
### CLI mode (non-interactive)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Execute a saved query
|
|
58
|
+
python -m dbqm run <query-name> --param1 value1
|
|
59
|
+
|
|
60
|
+
# Execute a query group
|
|
61
|
+
python -m dbqm run-group <group-name> --param1 value1
|
|
62
|
+
|
|
63
|
+
# Execute ad-hoc SQL
|
|
64
|
+
python -m dbqm sql "SELECT * FROM table" <connection>
|
|
65
|
+
|
|
66
|
+
# Test connections
|
|
67
|
+
python -m dbqm test [connection]
|
|
68
|
+
|
|
69
|
+
# List resources
|
|
70
|
+
python -m dbqm list connections|queries|groups
|
|
71
|
+
|
|
72
|
+
# Extract DDL
|
|
73
|
+
python -m dbqm ddl <object> <connection>
|
|
74
|
+
|
|
75
|
+
# Export/Import configs
|
|
76
|
+
python -m dbqm export-config
|
|
77
|
+
python -m dbqm import-config <file.dbqm>
|
|
78
|
+
|
|
79
|
+
# View history
|
|
80
|
+
python -m dbqm history
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Output format options: `--format table|json|csv` and `--export csv|json|txt`.
|
|
84
|
+
|
|
85
|
+
## Keyboard Navigation
|
|
86
|
+
|
|
87
|
+
The application is fully keyboard-driven:
|
|
88
|
+
|
|
89
|
+
| Key | Action | Context |
|
|
90
|
+
|-----|--------|---------|
|
|
91
|
+
| `↑` `↓` | Navigate items / widgets | Sidebar, lists, tables, forms |
|
|
92
|
+
| `←` `→` | Switch folder tabs | Query/group lists |
|
|
93
|
+
| `Enter` | Select / Confirm | Global |
|
|
94
|
+
| `Escape` | Go back | Global |
|
|
95
|
+
| `Ctrl+B` | Toggle sidebar | Global |
|
|
96
|
+
| `Ctrl+Q` | Quit | Global |
|
|
97
|
+
| `/` | Search / filter | Lists |
|
|
98
|
+
| `?` | Help (shortcuts) | Global |
|
|
99
|
+
| `Tab` | Next widget | Forms, settings |
|
|
100
|
+
| `V` | Vertical view | Query results |
|
|
101
|
+
| `E` | Export | Query/group results |
|
|
102
|
+
| `R` | Re-execute | Query/group results |
|
|
103
|
+
| `F` | Toggle flat/pivoted | Group results |
|
|
104
|
+
| `S` | Filter by status | Group results |
|
|
105
|
+
| `H` | HTML report | Group results |
|
|
106
|
+
| `X` | Clear history | History |
|
|
107
|
+
| `N` | New item | Connections, queries |
|
|
108
|
+
| `D` | Delete / Details | Connections, history |
|
|
109
|
+
| `C` | Compile Spec | Package editor |
|
|
110
|
+
| `B` | Compile Body | Package editor |
|
|
111
|
+
|
|
112
|
+
## Sidebar
|
|
113
|
+
|
|
114
|
+
| Section | Options |
|
|
115
|
+
|---------|---------|
|
|
116
|
+
| **Consultas** | Executar, SQL avulso, Gerenciar |
|
|
117
|
+
| **Grupos** | Executar, Gerenciar |
|
|
118
|
+
| **Ferramentas** | DDL, Packages, Objetos, Historico |
|
|
119
|
+
| **Sistema** | Conexoes, Config (inclui Exportar/Importar), Sair |
|
|
120
|
+
|
|
121
|
+
## Query Groups & Comparison
|
|
122
|
+
|
|
123
|
+
Groups run the same logical query across multiple databases and compare results:
|
|
124
|
+
|
|
125
|
+
- Define a **join key** (row identifier) and **comparison columns**
|
|
126
|
+
- Optional **normalization mapping** for semantic equivalence (e.g., "paga" = "pago")
|
|
127
|
+
- Optional **column mapping** for mismatched column names
|
|
128
|
+
- Results show status per row: `OK`, `DIFF`, `ABSENT`
|
|
129
|
+
- Two display modes: **flat** (one table per column) and **pivoted** (one table per key)
|
|
130
|
+
- Filter results by status (divergent, absent, or combined)
|
|
131
|
+
- Export as HTML report with interactive filters
|
|
132
|
+
|
|
133
|
+
## Project Structure
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
dbqm/
|
|
137
|
+
├── main.py # Entry point
|
|
138
|
+
├── requirements.txt # Dependencies
|
|
139
|
+
├── dbqm/
|
|
140
|
+
│ ├── __main__.py # python -m dbqm support
|
|
141
|
+
│ ├── cli.py # Non-interactive CLI
|
|
142
|
+
│ ├── ui/
|
|
143
|
+
│ │ ├── app.py # Main Textual App (layout, routing, keybindings)
|
|
144
|
+
│ │ ├── theme.py # GitHub Dark/Light theme definitions
|
|
145
|
+
│ │ ├── utils.py # sanitize_id, escape_markup utilities
|
|
146
|
+
│ │ ├── screens/ # Screen widgets (one per feature)
|
|
147
|
+
│ │ │ ├── query_exec.py # Execute saved query
|
|
148
|
+
│ │ │ ├── query_manage.py # Query CRUD, DE-PARA, SQL viewer
|
|
149
|
+
│ │ │ ├── group_exec.py # Execute group comparison
|
|
150
|
+
│ │ │ ├── group_manage.py # Group CRUD
|
|
151
|
+
│ │ │ ├── adhoc.py # Ad-hoc SQL execution
|
|
152
|
+
│ │ │ ├── ddl.py # DDL extraction
|
|
153
|
+
│ │ │ ├── browser.py # Object browser (tables, views, packages)
|
|
154
|
+
│ │ │ ├── history.py # Execution history
|
|
155
|
+
│ │ │ ├── connections.py # Connection management
|
|
156
|
+
│ │ │ ├── package_editor.py # Oracle package editor (spec/body, compile)
|
|
157
|
+
│ │ │ ├── settings.py # Theme, audit toggle, export/import
|
|
158
|
+
│ │ │ └── config_port.py # Config export/import (used by settings)
|
|
159
|
+
│ │ ├── widgets/ # Reusable UI components
|
|
160
|
+
│ │ │ ├── sidebar.py # Collapsible sidebar with keyboard nav
|
|
161
|
+
│ │ │ ├── breadcrumb.py # Navigation breadcrumb
|
|
162
|
+
│ │ │ ├── result_table.py # DataTable with pagination + vertical view
|
|
163
|
+
│ │ │ ├── query_list.py # Query ListView with search/filter
|
|
164
|
+
│ │ │ ├── group_result.py # Flat/pivoted comparison display
|
|
165
|
+
│ │ │ ├── sql_viewer.py # Syntax-highlighted SQL display
|
|
166
|
+
│ │ │ ├── action_bar.py # Contextual keyboard shortcuts bar
|
|
167
|
+
│ │ │ ├── status_bar.py # Connection status + counters
|
|
168
|
+
│ │ │ └── progress.py # Loading indicator
|
|
169
|
+
│ │ ├── modals/ # Dialog screens
|
|
170
|
+
│ │ │ ├── param_input.py # Query parameter input
|
|
171
|
+
│ │ │ ├── confirm.py # Yes/No confirmation
|
|
172
|
+
│ │ │ ├── text_input.py # Single text input
|
|
173
|
+
│ │ │ ├── export_picker.py # Export format selector
|
|
174
|
+
│ │ │ ├── connection_form.py # Connection create/edit form
|
|
175
|
+
│ │ │ ├── column_maps.py # DE-PARA value mapping
|
|
176
|
+
│ │ │ ├── error.py # Error display modal
|
|
177
|
+
│ │ │ └── help.py # Keyboard shortcuts overlay
|
|
178
|
+
│ │ └── legacy/
|
|
179
|
+
│ │ └── display.py # Rich renderables for PNG/TXT export
|
|
180
|
+
│ ├── core/ # Business logic (database-agnostic)
|
|
181
|
+
│ │ ├── db_manager.py # Connection handling
|
|
182
|
+
│ │ ├── query_engine.py # SQL execution + parameter binding
|
|
183
|
+
│ │ ├── group_engine.py # Multi-database comparison
|
|
184
|
+
│ │ ├── exporter.py # Export (CSV, JSON, TXT, PNG)
|
|
185
|
+
│ │ ├── html_report.py # HTML comparison reports
|
|
186
|
+
│ │ ├── ddl_extractor.py # Oracle DDL (DBMS_METADATA)
|
|
187
|
+
│ │ ├── ddl_pg.py # PostgreSQL DDL
|
|
188
|
+
│ │ ├── ddl_mysql.py # MySQL DDL
|
|
189
|
+
│ │ ├── object_browser.py # Database object introspection
|
|
190
|
+
│ │ ├── table_browser.py # Table data browsing
|
|
191
|
+
│ │ ├── package_editor.py # Oracle package compile + errors
|
|
192
|
+
│ │ ├── crypto.py # Password encryption
|
|
193
|
+
│ │ ├── config_portability.py # Config import/export
|
|
194
|
+
│ │ ├── history.py # Execution history
|
|
195
|
+
│ │ └── audit.py # Audit logging
|
|
196
|
+
│ └── models/ # Data models (JSON persistence)
|
|
197
|
+
│ ├── connection.py # Connection config
|
|
198
|
+
│ ├── query.py # Query definition
|
|
199
|
+
│ ├── group.py # Query group config
|
|
200
|
+
│ └── settings.py # App settings (theme, audit)
|
|
201
|
+
├── config/ # JSON configs (gitignored)
|
|
202
|
+
├── exports/ # Generated output files (gitignored)
|
|
203
|
+
└── tests/ # Test suite (440+ tests)
|
|
204
|
+
├── core/ # Core logic tests
|
|
205
|
+
├── models/ # Model tests
|
|
206
|
+
└── ui/ # TUI widget/screen/modal tests
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Key Dependencies
|
|
210
|
+
|
|
211
|
+
| Library | Purpose |
|
|
212
|
+
|---------|---------|
|
|
213
|
+
| `textual` | Fullscreen TUI framework (layout, widgets, themes) |
|
|
214
|
+
| `rich` | Terminal formatting (used by Textual internally + exports) |
|
|
215
|
+
| `oracledb` | Oracle database driver |
|
|
216
|
+
| `pymssql` | SQL Server database driver |
|
|
217
|
+
| `psycopg` | PostgreSQL database driver (v3) |
|
|
218
|
+
| `PyMySQL` | MySQL database driver |
|
|
219
|
+
| `cryptography` | Fernet encryption for credentials |
|
|
220
|
+
| `sqlparse` | SQL analysis and classification |
|
|
221
|
+
| `Pillow` | PNG screenshot export |
|
|
222
|
+
|
|
223
|
+
## Security
|
|
224
|
+
|
|
225
|
+
- Database passwords encrypted at rest using Fernet (`.dbqm_key` master key)
|
|
226
|
+
- Configuration bundles use PBKDF2 (480,000 iterations) + Fernet
|
|
227
|
+
- Queries use bind variables to prevent SQL injection
|
|
228
|
+
- SQL identifiers validated against allowlist pattern
|
|
229
|
+
- Query results capped at 10,000 rows
|
|
230
|
+
- Config bundle imports limited to 10 MB
|
|
231
|
+
- HTML reports escape all user-controlled values
|
|
232
|
+
- Audit log files created with restricted permissions
|
|
233
|
+
- File open operations restricted to exports directory
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from dbqm._version import __version__
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|