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: keine eigene C++-Schnittstelle von Microsoft: Schlüssel von ODBC Driver 18 (für bestehende Programme bleibt der ODBC-Treiber der Weg) · Bibliothek ksqlcpp über ksqlkern, CMake-Ziel ksql::ksql (find_package(KuonenKsql)) · C++20, CMake · Quelle: Data/src/Kuonen.Data.Ksql.Cpp
· Roadmap D36.6 ✅
Herunterladen und einbinden
- kuonen-ksql-cpp-2.8.0.1-linux-x64.tar.gz · 233 KB
SHA-256
8cd1596a01b93fe7d5b0455051275073d95a39c757de2640f6e37b93cc91a29d
sudo mkdir -p /opt/ksql && sudo tar -xzf kuonen-ksql-cpp-2.8.0.1-linux-*.tar.gz -C /opt/ksql
# CMakeLists.txt des eigenen Programms:
# find_package(KuonenKsql CONFIG REQUIRED)
# target_link_libraries(meinprogramm PRIVATE ksql::ksql)
cmake -S . -B bau -DCMAKE_PREFIX_PATH=/opt/ksql && cmake --build bauKöpfe und die beiden statischen Bibliotheken (ksqlcpp, ksqlkern) für Linux (x64 oder arm64), gebaut mit g++ und OpenSSL 3; dazu die Paketbeschreibung für find_package.
Aus dem Quellcode bauen
cmake -S Data/src/Kuonen.Data.Ksql.Cpp -B bau [-DKSQL_TLS=openssl|apple|schannel] && cmake --build bau
cmake --install bau --prefix /opt/ksql # Köpfe, Bibliotheken, find_package(KuonenKsql)
# vcpkg (Overlay-Port) und Conan 2 (Rezept) sind vorbereitet, nicht veröffentlicht:
vcpkg install kuonen-ksql --overlay-ports=Data/src/Kuonen.Data.Ksql.Cpp/verteilung/vcpkg
conan create Data/src/Kuonen.Data.Ksql.Cpp/verteilung/conan --build=missingEin Programm bindet ksql::ksql (find_package(KuonenKsql CONFIG REQUIRED)). Die Fassung folgt der des Servers.
Verbindungszeichenfolge
Server=127.0.0.1,1333;UID=sa;PWD={<Ihr-Kennwort>};Encrypt=yes;TrustServerCertificate=yesOhne Port gilt 1433 wie beim Vorbild; den KSQL-Port 1333 nennt man.
| Schlüssel | Bedeutung |
|---|---|
Server | Rechner[,Port]; Vorgabeport 1433 wie bei ODBC Driver 18 |
UID, PWD, Database | SQL-Anmeldung; {…} um einen Wert erlaubt ; darin |
Encrypt | yes, no, strict |
TrustServerCertificate, HostNameInCertificate, ServerCertificate | Prüfung des Zertifikats |
APP, WSID, Language, PacketSize, LoginTimeout, ApplicationIntent | wie bei ODBC Driver 18 |
Beispiel: verbinden, abfragen, Parameter, Transaktion
#include <ksql/ksql.hpp>
auto v = ksql::verbindung::oeffne("Server=127.0.0.1,1333;UID=sa;PWD={…};Encrypt=yes;TrustServerCertificate=yes");
for (const ksql::zeile &z : v.ausfuehren("SELECT id, name FROM kunde WHERE ort = @p1", std::string("Sion")))
std::cout << z.get<int>(0) << ' ' << z.get<std::optional<std::string>>("name").value_or("-") << '\n';
auto t = v.beginne();
long long n = v.ausfuehren("UPDATE konto SET saldo = saldo - @betrag WHERE id = @id",
ksql::param("@betrag", ksql::dezimal("12.50")), ksql::param("@id", 7)).betroffen();
t.bestaetige(); // ohne bestaetige() nimmt der Zerstörer die Transaktion zurück
try {
v.ausfuehren("SELECT 1 / 0").zu_ende();
} catch (const ksql::fehler &e) { // e.nummer() 8134, e.klasse() 16, e.sqlstate() "22012" (am KSQL-Port)
}Typen
| SQL- bzw. KSQL-Typ | im Treiber |
|---|---|
| Parameter (Typ aus dem C++-Typ) | bool → bit, short → smallint, int → int, long long → bigint, std::uint8_t → tinyint, std::uint64_t → decimal(20,0), float → real, double → float, Text → nvarchar(4000|max), bytes → varbinary(8000|max), dezimal → decimal(p,s), guid → uniqueidentifier, year_month_day → date, uhrzeit → time(7), local_time → datetime2(7), zeit_mit_versatz und sys_time → datetimeoffset(7), std::optional<T> → NULL mit dem Typ von T |
| Werte (zeile::get<T>) | bool, Ganzzahlen, float/double, std::string, dezimal, guid, bytes, std::chrono::year_month_day, uhrzeit, ortszeit, zeit_mit_versatz, jeweils auch std::optional<T>; text(i) in der kanonischen Form des Prüfkatalogs |
| KSQL-Typen als Parameter | ksql::als{"int ARRAY", "{1,2}"} (in @params mit ihrem Namen deklariert); ksql::als nennt jeden anderen Typ ausdrücklich |
| ARRAY, ROW, MULTISET, INTERVAL als Wert | Text, keine eigenen C++-Typen |
Fehler und SQLSTATE
| Fall | Angaben |
|---|---|
| ksql::fehler | Hauptmeldung mit nummer(), klasse(), Zustand, sqlstate() und Text ohne den Zusatz; alle Meldungen in meldungen() |
| leitungsfehler | die Verbindung ist danach unbrauchbar |
| abbruch, fristablauf | HY008 bzw. HYT00 |
| wertfehler | 22002 NULL ohne optional, 22003 Bereich, 07006 Typ, 22018 Text, 07009 Spalte |
| HY010, 08003 | offene Antwort oder Massenkopie sperrt die Verbindung; Antwort, Transaktion und Massenkopie nach ihrer Verbindung |
Unterschiede zu keine eigene C++-Schnittstelle von Microsoft: Schlüssel von ODBC Driver 18 (für bestehende Programme bleibt der ODBC-Treiber der Weg)
- Microsoft liefert keine C++-Schnittstelle; Vorbild sind die Schlüssel von ODBC Driver 18, die Schnittstelle selbst ist eigen (RAII, Ausnahmen, typsichere Parameter, deutsche Namen).
- Ein Fehler des Servers wird an der nächsten Grenze geworfen (Ende der Zeilen, naechste_menge(), zu_ende()); danach lässt sich die Antwort weiterlesen.
- Der Zerstörer liest zu Ende, nimmt die Transaktion zurück und schliesst.
Was fehlt
- Vorbereitete Anweisungen (sp_prepare-Kennung behalten), MARS, Tabellenwertparameter, Always Encrypted.
- Integrierte Anmeldung und Entra ID, eine asynchrone Schnittstelle (Koroutinen), ein Pool.
- Eigene C++-Typen für ARRAY, ROW, MULTISET und INTERVAL.
- Windows (MSVC, SChannel) nicht gebaut; Verteilung nur vorbereitet (kein Register, kein Conan-Remote).
| Restzeile | Beschreibung | Stand |
|---|---|---|
D36.6a Rest aus D36.6 | **Teilweise erledigt 21.10.2026:** `ksql::anweisung` (vorbereitet: erster Lauf `sp_prepexec`, dann `sp_execute` mit der behaltenen Kennung, `sp_unprepare` im Zerstörer oder mit der nächsten Anfrage; nach Namen aufgerufen, denn über die Kennung nimmt SQL Server bei `sp_execute` keine benannten Parameter an, 4002), die KSQL-Typen als eigene C++-Typen `intervall`, `sammlung` (ARRAY, MULTISET) und `zeilenwert` (ROW) zum Lesen und als Parameter (Textformen wie der Java-Treiber, Tiefe und Länge gedeckelt), `ksql::pool` für mehrere Fäden. Tests ohne Server 115, mit Server am KSQL-Port 136 und am Orakel 128 Prüfungen, je ohne Fehlschlag, auf dem Mac und im Container (dort als Bauschritt); Katalog im Container am KSQL-Port 82 ok, 0 abweichend, 0 Befunde, am Orakel 72 ok, 10 übersprungen. Gegenprobe: ohne das Abfangen der Kennung vier Fehlschläge. **Offen:** (1) Windows (MSVC, SChannel); macOS nur von Hand übersetzt (lokal fehlt CMake). (2) Kein .NET-Test wie `JavaTreiberTests`. (3) MARS, Tabellenwertparameter, Always Encrypted, integrierte Anmeldung und Entra ID, eine asynchrone Schnittstelle (Koroutinen); der Pool setzt den Sitzungszustand nicht zurück (kein RESETCONNECTION). (4) Verteilung nur vorbereitet; die Fassung in `vcpkg.json` ist von Hand nachzuführen. **Erledigt 21.10.2026:** (2) `TreiberPruefstandTests` (Bauschritt, `KUONENSQL_DOCKER_ABNAHME=1`) baut den Prüfstand `cpp/` (g++ 12 in `debian:bookworm-slim`, Tests mit Sanitizern, `find_package`-Probe, Abspieler) und spielt den Katalog am KSQL-Port und am Orakel ab - 2 von 2 grün. Der erste Lauf auf x64 fand einen Fehler, den clang auf dem Mac verdeckte: `sammlung::von` rief `elementtyp_aus(…, texte)` und `std::move(texte)` in derselben Argumentliste; g++ wertet von rechts aus, die Texte waren schon weg und eine Sammlung aus `dezimal` wurde `decimal(1,0)` statt `decimal(4,2)` (Prüfung „von dezimal“ rot). Jetzt wird der Typ vorher berechnet. Rest in D36.6g. | ✅ |
D36.6e Rest aus D36.6d | (1) `sp_executesql` prüft die Werte nicht: SQL Server meldet 8178 (RETURNSTATUS 1) bzw. 8144 auch dort, KuonenSQL setzt NULL bzw. meldet 137; ebenso fehlen dort 352 und 102 für die Parameterliste. (2) Am Orakel hängt das Ergebnis eines fehlenden Werts am Plan-Cache: ist die Anweisung noch nicht übersetzt, kommt 8178 mit 8180 und RETURNSTATUS 8180 statt RETURNSTATUS 1 (einmal beobachtet) - KuonenSQL antwortet immer wie mit Plan. (3) Der RETURNSTATUS von `EXEC sp_prepare` im Stapel ist am Orakel der Status des vorigen Aufrufs auf der Verbindung (z. B. 8178 nach einem gescheiterten sp_prepexec); KuonenSQL schickt 0. (4) Ein Übersetzungsfehler einer Datenänderung (`INSERT` in eine fehlende Tabelle) bei `sp_prepare` ist nicht gemessen; KuonenSQL beschreibt sie ohne Prüfung. **Erledigt 21.10.2026** (am Orakel gemessen, SqlClient 6.1.6 mit Mitschnitt): (1) `sp_executesql` prüft über RPC und im Stapel die Parameterliste (352, 102) und die Werte (8178, 8144), dazu Werte ohne Liste (214 Zustand 3) und mit leerer Liste (8146, RETURNSTATUS 1); der Aufruf endet, der Stapel läuft weiter, `EXEC @r = …` trägt den Status. (2) Gemessen ist die Regel: der Status hängt daran, ob dieselbe Anweisung mit derselben Parameterliste schon übersetzt ist (aus `sp_executesql`, `sp_prepexec` oder `sp_prepare`, über Verbindungen hinweg) - dann 8178 mit RETURNSTATUS 1 und 8144 als Fehler der EXEC-Anweisung (curCmd 0x00FD, ohne Status, bricht den Stapel ab), sonst bei `sp_executesql` RETURNSTATUS gleich Fehlernummer, bei `sp_prepexec` 8180 samt Meldung 8180. KuonenSQL führt dafür je Datenbank einen gedeckelten `Planbestand`. (3) Der RETURNSTATUS von `sp_prepare` (RPC und Stapel) ist `@@ERROR` vor dem Aufruf, und `@@ERROR` gilt über das Ende eines Stapels hinaus (auch das war bei KuonenSQL anders); ein DECLARE ohne Wert und `sp_prepare` lassen es stehen, `sp_unprepare` und SET setzen es auf 0. (4) INSERT, UPDATE und DELETE an einer fehlenden Tabelle: 208, 8180, RETURNSTATUS 8180, Griff NULL. Tests `AusfuehrungsWerteTests` (37, vorher 35 rot), angepasst `VorbereiteteAnweisungenResteTests` (frische Anweisungen jetzt mit 8180). Rest in D36.6f. | ✅ |
D36.6f Rest aus D36.6e | (1) Am Orakel meldet `sp_prepare` für `INSERT sys.objects …` 259 („Ad hoc updates to system catalogs are not allowed.“) mit 8180; KuonenSQL kennt 259 nicht. (2) Nicht gemessen: ob `sp_reset_connection` `@@ERROR` zurücksetzt (KuonenSQL behält es), ob der Plan-Cache des Orakels auch nach den SET-Optionen unterscheidet (der `Planbestand` nur nach Datenbank, Liste und Text) und was `sp_prepare` bei MERGE, `UPDATE … FROM` und Zielen in einer anderen Datenbank prüft (KuonenSQL prüft dort nichts vor). (3) Ob ein DECLARE mit Wert oder ein DECLARE einer Tabellenvariablen `@@ERROR` stehen lässt, ist nicht gemessen (KuonenSQL setzt es auf 0). | ⬜ |
D36.6g Rest aus D36.6a | (1) Windows (MSVC, SChannel); macOS nur von Hand übersetzt (lokal fehlt CMake). (2) MARS, Tabellenwertparameter, Always Encrypted, integrierte Anmeldung und Entra ID, eine asynchrone Schnittstelle (Koroutinen); der Pool setzt den Sitzungszustand nicht zurück (kein RESETCONNECTION). (3) Verteilung nur vorbereitet; die Fassung in `vcpkg.json` ist von Hand nachzuführen. | ⬜ |
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.
Eigener Code ohne fremde Quellen; TLS kommt wie im Kern aus der Bibliothek des Systems. vcpkg und Conan vorbereitet, nicht veröffentlicht.