Kuonen SQL

KSQL-Treiber

Eigene Treiber für den KSQL-Port (TDS 7.4 mit dem KSQL-Profil) in acht Sprachen, je nach dem Vorbild des Microsoft-Treibers: dieselbe Schnittstelle, dieselben Schlüssel der Verbindungszeichenfolge, dieselbe Abbildung der Typen und Fehler — und dazu, was KSQL über SQL Server hinaus kann. Jeder arbeitet auch an SQL Server. Jeder Treiber spielt denselben sprachneutralen Prüfkatalog ab (KuonenSQL/tools/ksql-konformitaet/faelle.json, D36.1), einmal gegen den KSQL-Port und einmal gegen SQL Server 2025.

Vorbild: mssql-python bzw. DB-API 2.0 (PEP 249) · Paket ksql, Paketname kuonen-ksql (pyproject.toml) · Python 3.10+, nur Standardbibliothek (TLS über ssl) · Quelle: Data/src/Kuonen.Data.Ksql.Python · Roadmap D36.7 ✅

Herunterladen und einbinden

Befehle
pip install kuonen_ksql-2.0.0-py3-none-any.whl
# dann im Code:  import ksql

Reines Python ohne Abhängigkeiten, ab Python 3.10. Das Paket geht nicht auf PyPI.

Aus dem Quellcode bauen

Befehle
cd Data/src/Kuonen.Data.Ksql.Python
python -m unittest discover -s tests          # Robustheit gegen verfälschte Antworten, Einheiten

Das Paket ksql liegt im Ordner ksql/ und wird über pyproject.toml gebaut (Paketname kuonen-ksql), ohne Fremdabhängigkeiten. Es trägt „Private :: Do Not Upload“ und geht nicht auf PyPI.

Verbindungszeichenfolge

Server=localhost,1333;UID=sa;PWD=<Ihr-Kennwort>;Encrypt=yes;TrustServerCertificate=yes

Ohne Port gilt 1333 (der KSQL-Port).

SchlüsselBedeutung
Serverhost,port (Vorgabeport 1333)
Database, UID, PWDAnmeldung
Encryptyes, no, strict
TrustServerCertificate, HostNameInCertificatePrüfung des Zertifikats
Connect Timeout, APP, WSID, Packet Size, ApplicationIntentwie bei ODBC Driver 18
connect(…, autocommit=False, timeout=0)Autocommit und Befehlsfrist

Beispiel: verbinden, abfragen, Parameter, Transaktion

Python
import ksql

conn = ksql.connect("Server=localhost,1333;UID=sa;PWD=…;Encrypt=yes;TrustServerCertificate=yes", autocommit=True)
cur = conn.cursor()
cur.execute("SELECT name FROM sys.tables WHERE name LIKE ?", ("kk_%",))
print(cur.fetchall())

conn.begin()                                  # Transaction-Manager-Anfrage
cur.execute("UPDATE konto SET saldo = saldo - ? WHERE id = ?", (1, 7))
conn.commit()

try:
    cur.execute("SELECT 1 / 0")
except ksql.DataError as e:                   # e.number 8134, e.sqlstate "22012"
    print(e.number, e.sqlstate)

Typen

SQL- bzw. KSQL-Typim Treiber
Typen von SQL Serverwie PEP 249 und mssql-python; Parameter mit ksql.Param(value, sqltype, direction, name), etwa decimal(9,2) oder nvarchar(max)
BOOLEANbool
DECFLOATdecimal.Decimal
INTERVAL, ROW, ARRAY, MULTISETdie Textklassen ksql.Interval, ksql.Row, ksql.Array, ksql.Multiset
time(7), datetime2(7)ksql.Zeit, ksql.Zeitpunkt: die siebte Stelle steht in nanosecond
Cursor.column_typesdie SQL-Typen der Spalten, KSQL-Typen mit ihrem Namen auf der Leitung

Fehler und SQLSTATE

FallAngaben
Ausnahmen nach PEP 249DataError (SQLSTATE-Klasse 22), IntegrityError, ProgrammingError, OperationalError …
Feldernumber, severity, state, message, sqlstate und server_sqlstate
sqlstate am KSQL-Portder Zustand der Norm vom Meldungsende
sqlstate an SQL Serveraus der Nummer wie die ODBC-Treiber von Microsoft; server_sqlstate ist dort None
cancel(), timeoutOperationalError mit HY008 bzw. HYT00

Unterschiede zu mssql-python bzw. DB-API 2.0 (PEP 249)

  • paramstyle qmark (?); dazu @name mit einer Zuordnung oder ksql.Param(name=…).
  • Cursor.callproc mit Rückgabestatus in return_value, Cursor.bulkcopy für die Massenkopie, Cursor.cancel() per ATTENTION auch aus einem anderen Faden.
  • Connection.begin(), .savepoint(name), .rollback(savepoint=…) über die Transaction-Manager-Anfrage.
  • Vorgabeport 1333.

Was fehlt

  • Benannte Instanzen (SQL Browser), Windows- und Entra-Anmeldung, MARS, Umleitung (ENVCHANGE 20).
  • Always Encrypted, Tabellenwertparameter.
  • Verteilung über PyPI erst nach Entscheid von Marc (Code bleibt geschlossen).
RestzeileBeschreibungStand
D36.7f Rest aus D36.7e(1) `docker run` startete am 21.10. keinen Container; `pruefstand.ps1` und ein Test wie `DockerPruefstandTests` für Python und Go sind noch nicht durchgelaufen (die Läufe gingen als Bauschritte). (2) Beide: keine Windows- oder Entra-Anmeldung, kein Always Encrypted; Go: `TVP` nicht als `sql.Out`; der SQL Browser nur gegen einen nachgebauten, nicht gegen einen echten SQL-Server-Browser; die Umleitung nur gegen einen falschen Server (der KSQL-Port leitet nur bei Lesezugriff auf eine Kopie um). (3) Python liest Codepages über `codecs`: undefinierte Byte werden zum Ersatzzeichen bzw. zum Byte gleicher Nummer, SQL Server nennt dafür teils Zeichen der privaten Zone (Messung in D36.7e). (4) Verteilung: das Python-Paket trägt „Private :: Do Not Upload“, das Go-Modul `kuonen.org/ksql` braucht einen Ort, der den Importpfad ausliefert - beides erst nach Entscheid von Marc (Code bleibt geschlossen). (5) `tools/roadmap.py` braucht Python 3.10+, lokal gibt es 3.9: Status von Hand gesetzt, `nachziehen` nicht gelaufen. **Erledigt 21.10.2026:** (1) `PythonGoPruefstandTests` (Bauschritt wie `OdbcPruefstandTests`, `KUONENSQL_DOCKER_ABNAHME=1`): Python (`python:3.12-slim`, 23 Tests im Bau) und Go (`golang:1.23`, gofmt, vet, Tests im Bau) bestehen den Katalog am KSQL-Port (0 abweichend, 0 übersprungen) und an SQL Server 2025 (nur die Fälle „nur ksql“ übersprungen) - 4 von 4 grün. Dafür liegen die Go-Quellen mit LF im Arbeitsbaum (`.gitattributes` des Treibers; unter Windows scheiterte `gofmt -l` an CRLF) und beide Abbilder haben ein `Dockerfile.dockerignore`. (3) Am Orakel gemessen (je eine Datenbank in der Sortierung, alle Byte 0x80-0xFF von 12 Einzelbyte-Codepages): abweichend von den Codecs nur 874 (DB-DE, FC-FF → U+F8C1-F8C8), 1253 (AA, D2, FF → U+F8F9-F8FB), 1255 (CA → U+05BA, D9-DF, FB, FC, FF → U+F88D-F896) und 1257 (A1, A5 → U+F8FC, F8FD); der Python-Treiber liest sie so und schreibt sie zurück zu ihrem Byte (je Codepage ein Fehlerbehandler `ksql-roh-<cp>`, Test `test_undefinierte_byte_der_codepages_wie_sql_server`, vorher rot; Sabotage ohne die Tabelle rot). (5) `tools/roadmap.py` läuft mit Python 3.14: `pruefen` bestätigt die von Hand gesetzten Stände der Meilensteine (nur Datum und Fassung der Kopfzeilen wären nachzuziehen). Python lokal (3.14) 24 Tests, 3 übersprungen. Rest in D36.7h.✅
D36.7h Rest aus D36.7f(1) Beide: keine Windows- oder Entra-Anmeldung, kein Always Encrypted; Go: `TVP` nicht als `sql.Out`; der SQL Browser nur gegen einen nachgebauten, nicht gegen einen echten SQL-Server-Browser; die Umleitung nur gegen einen falschen Server (der KSQL-Port leitet nur bei Lesezugriff auf eine Kopie um). (2) Mehrbyte-Codepages (932, 936, 949, 950): wie in D36.7e gemessen; die Byte ohne Zeichen in den Einzelbyte-Codepages 437, 850 und 1250-1258 ausser den gemessenen sind Zeichen gleicher Nummer. (3) **Entscheid von Marc:** Verteilung - das Python-Paket trägt „Private :: Do Not Upload“, das Go-Modul `kuonen.org/ksql` braucht einen Ort, der den Importpfad ausliefert (Code bleibt geschlossen).⬜

Herkunft und Lizenz

Eigenbau: übernommen sind nur die Schnittstelle des Microsoft-Treibers und das am Orakel (SQL Server 2025) gemessene Verhalten, kein Code – auch nicht aus MIT- oder BSD-lizenzierten Quellen –, damit der Treiber uneingeschränkt KuonenSQL gehört. Der Code bleibt geschlossen; eine Veröffentlichung gibt es nur als eigenständigen Fork, den Marc Kuonen selbst anlegt.

Kein Code von mssql-python; nur Standardbibliothek. Das Paket trägt „Private :: Do Not Upload“.