ResultSet fetch methods silently return empty after close instead of raising (PEP 249 §Cursor)

Offen
#792 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
55/100
Issue-Typ
Bug
Klarheit
Größtenteils klar
Aktivitätsstatus
Ruhig
Tech-Stack
python

Rechercherichtung

Beginne in src/databricks/sql/result_set.py und verfolge dann die Fetch-Methoden von ThriftResultSet, SeaResultSet und KernelResultSet. Reproduziere zuerst das Beispiel für einen geschlossenen Cursor und untersuche, wie close() den bestehenden Status und die Erschöpfungs-Flags setzt. Die Aufgabe ist abgeschlossen, wenn jede aufgeführte Fetch-Methode nach close() für alle drei Backends InterfaceError auslöst, das Verhalten gemäß PEP 249 verifiziert ist und der Kompatibilitätshinweis berücksichtigt wurde.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

enhancement

Summary

PEP 249 §Cursor says fetch operations on a closed cursor should raise an exception. Today, all three result-set implementations (ThriftResultSet, SeaResultSet, KernelResultSet) silently return empty after close() rather than raising InterfaceError.

Repro

import databricks.sql

with databricks.sql.connect(...) as conn:
    cur = conn.cursor()
    cur.execute("SELECT 1")
    cur.close()
    cur.fetchall()  # PEP 249 says raise; today returns [].

Root cause

# src/databricks/sql/result_set.py — base ResultSet.close():
def close(self) -> None:
    ...
    finally:
        self.has_been_closed_server_side = True
        self.status = CommandState.CLOSED

The flag is set, but the fetch methods don't read it. They walk self.results (an internal queue) which has been closed; next_n_rows returns empty rather than raising. KernelResultSet has the same shape with self._exhausted = True in close, which short-circuits its fetch loop to empty.

Scope

All three backends. This is a project-wide PEP 249 compliance gap, not specific to the kernel backend.

Concurrent fetch-vs-close (related)

There is no _closed flag readable by concurrent threads — if one thread is mid-fetch while another calls close(), behaviour is undefined (likely AttributeError from a nulled handle). Cursors are documented as not thread-safe, so this is "not a bug" by design, but a single _closed flag would make accidental misuse fail cleanly with InterfaceError instead of AttributeError.

Suggested fix

In base ResultSet (src/databricks/sql/result_set.py):

  1. Add self._closed: bool = False. Set to True inside close() after cleanup.
  2. Add a private _check_open() that raises InterfaceError("Result set is closed") if _closed.
  3. Call _check_open() at the top of every fetch method (fetchone, fetchmany, fetchall, fetchmany_arrow, fetchall_arrow).

Backwards-compat note: any user code that defensively does cur.close(); cur.fetchall() expecting [] will start raising. Likely warrants a release note.

Surfaced by

Review of PR #787 (kernel backend). Documented as P1 #8 + #9 in https://github.com/databricks/databricks-sql-python/pull/787#issuecomment-4475165482 — but the gap is pre-existing on Thrift and SEA too, not specific to the kernel backend.

Vorherrschende Sprache
Python
Sterne
233
Forks
152
Ø Merge
21 Std. 5 Min.
Gemergte PRs (30 T.)
10

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus databricks/databricks-sql-python

Alle Issues in databricks/databricks-sql-python

Ähnliche Issues

Weitere Issues zu Python

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.