Skip to content

Commit f0f6922

Browse files
lukischclaude
andcommitted
fix: bulk bugfix session 2026-03-13 -- SQLiteViewer enhancements and task notes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fdcff8c commit f0f6922

2 files changed

Lines changed: 42 additions & 6 deletions

File tree

AUFGABEN.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
AUFGABEN - REL-PUB_SQLiteViewer
2+
================================
3+
Stand: 13.03.2026
4+
5+
## BUGFIXES (Session 2026-03-13, Claude Opus)
6+
7+
[x] MITTEL: Read-only Modus -- DB wird jetzt via URI im ro-Modus geoeffnet
8+
[x] MITTEL: SELECT-Erkennung case-insensitiv -- .upper() + WITH/EXPLAIN/PRAGMA abgedeckt
9+
[x] MITTEL: Column Headers bei leerem Ergebnis -- cur.description Guard gegen None
10+
[x] MITTEL: WM_DELETE_WINDOW -- _on_close Handler registriert, DB wird sauber geschlossen
11+
12+
## OFFENE BUGS
13+
14+
(keine bekannten)
15+
16+
## GITHUB-POLICY Compliance (Stand: 05.03.2026)
17+
Referenz: .SOFTWARE/GITHUB-POLICY.md
18+
19+
[x] README.md zweisprachig (DE-Abschnitt fehlt) -- DONE 2026-03-08 (Sonnet-Pruefung: DE-Abschnitt bereits vollstaendig vorhanden, EN-Abschnitt ebenfalls vorhanden)
20+
[x] requirements.txt -- bereits vorhanden (stdlib only, ATI-Pruefung 2026-03-08)

SQLiteViewer.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ def __init__(self):
5151
# Styling
5252
self._setup_styles()
5353

54+
# BUG 4: Sauberes Schließen via WM_DELETE_WINDOW
55+
self.protocol("WM_DELETE_WINDOW", self._on_close)
56+
5457
def _setup_styles(self):
5558
"""Konfiguriere ttk Styles."""
5659
style = ttk.Style()
@@ -288,7 +291,7 @@ def open_db(self):
288291
self.close_db()
289292

290293
try:
291-
conn = sqlite3.connect(path)
294+
conn = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
292295
conn.row_factory = sqlite3.Row
293296
self.conn = conn
294297
self.db_path = path
@@ -341,7 +344,10 @@ def load_selected_table(self):
341344
if not table or not self.conn:
342345
return
343346

344-
limit = max(1, int(self.limit_var.get() or DEFAULT_LIMIT))
347+
try:
348+
limit = max(1, int(self.limit_var.get()))
349+
except (ValueError, TypeError):
350+
limit = DEFAULT_LIMIT
345351

346352
try:
347353
# Spalten bestimmen
@@ -501,16 +507,21 @@ def execute_sql(self):
501507
start_time = datetime.now()
502508
cur = self.conn.execute(sql)
503509

504-
# Prüfe ob SELECT-Statement
505-
if sql.upper().strip().startswith("SELECT"):
510+
# Prüfe ob SELECT-artiges Statement (BUG 2: WITH/EXPLAIN/PRAGMA eingeschlossen)
511+
sql_upper = sql.upper().strip()
512+
if sql_upper.startswith(("SELECT", "WITH", "EXPLAIN", "PRAGMA")):
506513
rows = cur.fetchall()
514+
# BUG 3: Spaltenheader auch bei leeren Ergebnissen auslesen
515+
cols = [desc[0] for desc in cur.description] if cur.description else []
507516
if rows:
508-
cols = [desc[0] for desc in cur.description]
509517
self._populate_sql_result(cols, rows)
510518
elapsed = (datetime.now() - start_time).total_seconds()
511519
self.sql_status.config(text=f"✓ {len(rows)} Zeilen in {elapsed:.3f}s")
512520
else:
513-
self._clear_sql_result()
521+
if cols:
522+
self._populate_sql_result(cols, [])
523+
else:
524+
self._clear_sql_result()
514525
self.sql_status.config(text="✓ Keine Ergebnisse")
515526
else:
516527
self.conn.commit()
@@ -728,6 +739,11 @@ def _ident(self, name: str) -> str:
728739
def _set_status(self, text: str):
729740
self.status_var.set(text)
730741

742+
def _on_close(self):
743+
"""Sauberes Schließen: DB schließen, dann Fenster zerstören."""
744+
self.close_db()
745+
self.destroy()
746+
731747
def _show_about(self):
732748
messagebox.showinfo(
733749
"Über SQLite Viewer",

0 commit comments

Comments
 (0)