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: sqlsrv und pdo_sqlsrv · Erweiterung ksql: Funktionen sqlsrv_* und PDO-Treiber ksql: · PHP 8.2+ (gebaut und geprüft mit PHP 8.3 auf Linux), OpenSSL · Quelle: Data/src/Kuonen.Data.Ksql.Php
· Roadmap D36.4 ✅
Herunterladen und einbinden
Kein Download: die PHP-Erweiterung wird aus dem Quellcode gebaut, und der Code bleibt geschlossen (ein PECL-Paket wäre Quelltext). Auf Anfrage bei Marc Kuonen.
Aus dem Quellcode bauen
cd Data/src/Kuonen.Data.Ksql.Php && phpize && ./configure --enable-ksql && make && make install
echo extension=ksql > /etc/php/conf.d/ksql.iniconfigure kopiert den Kern aus ../Kuonen.Data.Ksql.C nach kern/; der Port folgt darum dem Kern (ohne Angabe 1433). Die Fassung folgt der des Servers.
Verbindungszeichenfolge
ksql:Server=server,1333;Database=master;TrustServerCertificate=yesOhne Port gilt 1433 wie beim Vorbild; den KSQL-Port 1333 nennt man.
| Schlüssel | Bedeutung |
|---|---|
Server | wie bei ODBC (Rechner\Instanz ohne Port fragt den SQL Browser); bei sqlsrv_connect das erste Argument, etwa tcp:server,1333 |
Database, UID, PWD | Anmeldung (bei PDO Benutzer und Kennwort als Argumente) |
Encrypt | Vorgabe yes wie ODBC Driver 18, auch strict |
TrustServerCertificate, HostNameInCertificate, ServerCertificate | Prüfung des Zertifikats |
LoginTimeout, APP, WSID, Language, ApplicationIntent, PacketSize | wie bei sqlsrv |
TransactionIsolation, ReturnDatesAsStrings | wie bei sqlsrv |
KsqlCancelAfterMs, PDO::KSQL_ATTR_CANCEL_AFTER_MS, PDO::KSQL_ATTR_QUERY_TIMEOUT | eigene: Abbruch nach dieser Zeit (HY008), Befehlsfrist in Sekunden (HYT00) |
Beispiel: verbinden, abfragen, Parameter, Transaktion
$c = sqlsrv_connect('tcp:server,1333', ['Database' => 'master', 'UID' => 'sa', 'PWD' => $pw, 'TrustServerCertificate' => true]);
$s = sqlsrv_query($c, 'SELECT name FROM sys.tables WHERE name LIKE ?', ['kk_%']);
while ($z = sqlsrv_fetch_array($s, SQLSRV_FETCH_ASSOC)) { echo $z['name'], "\n"; }
sqlsrv_begin_transaction($c);
sqlsrv_query($c, 'UPDATE konto SET saldo = saldo - ? WHERE id = ?', [1, 7]);
sqlsrv_commit($c);
if (sqlsrv_query($c, 'SELECT 1 / 0') === false) {
print_r(sqlsrv_errors()); // SQLSTATE 22012, code 8134
}
// PDO
$pdo = new PDO('ksql:Server=server,1333;Database=master;TrustServerCertificate=yes', 'sa', $pw,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$s = $pdo->prepare('SELECT :a + 1 AS r');
$s->execute(['a' => 41]);Typen
| SQL- bzw. KSQL-Typ | im Treiber |
|---|---|
| sqlsrv: Ganzzahlen und bit | int |
| sqlsrv: Gleitkomma | float |
| sqlsrv: Dezimal und Geld | Text |
| sqlsrv: Zeit | DateTime (oder Text mit ReturnDatesAsStrings) |
| Binäres | Bytes |
| PDO | Werte als Text wie pdo_sqlsrv (bit 1/0, Binäres als Bytes); PDO::PARAM_INT → int bzw. bigint, PARAM_STR → nvarchar, PARAM_BOOL → bit, PARAM_LOB → varbinary(max) |
| INTERVAL, DECFLOAT, ROW, ARRAY, MULTISET | Text in der kanonischen Form; sqlsrv_field_metadata nennt KsqlType (etwa INTERVAL DAY(2)) und KsqlTypeName, getColumnMeta ksql:type und ksql:decl_type |
Fehler und SQLSTATE
| Fall | Angaben |
|---|---|
| sqlsrv_errors() | SQLSTATE, code, message wie sqlsrv; dazu severity und state |
| PDO::errorInfo, PDOException | SQLSTATE, Nummer, Text; dazu Klasse und Zustand in [3] und [4] |
| SQLSTATE am KSQL-Port | der vom Meldungsende (aus dem Kern) |
| SQLSTATE an SQL Server | wie die Microsoft-Treiber aus der Nummer (Kern) |
Unterschiede zu sqlsrv und pdo_sqlsrv
- Eine Erweiterung für beide Schnittstellen: die sqlsrv_*-Funktionen und der PDO-Treiber mit DSN ksql: statt sqlsrv:.
- Die Werte von SQLSRV_SQLTYPE_* und SQLSRV_PHPTYPE_* sind eigene Kodierungen; Programme, die die Namen nutzen, merken nichts.
- SQLSRV_SQLTYPE_TIME(s), _DATETIME2(s), _DATETIMEOFFSET(s) mit Skala.
- Eigene Massenkopie ksql_bulk_copy bzw. $pdo->ksqlBulkCopy(…) und $pdo->ksqlMeldungen() für PRINT und RAISERROR bis Klasse 10.
- PHP hat keinen zweiten Faden für sqlsrv_cancel: dafür KsqlCancelAfterMs.
- PDO::PARAM_STR geht als nvarchar, der Server wandelt in den deklarierten Typ (wie pdo_sqlsrv).
Was fehlt
- Rollbare Cursor (Scrollable nur forward; sqlsrv_num_rows meldet das), Ströme (SQLSRV_PHPTYPE_STREAM liefert den ganzen Wert).
- MARS, Verbindungspool, Windows- und Entra-Anmeldung, CharacterSet (immer UTF-8), Always Encrypted.
- Verteilung: kein PECL-Paket (package.xml), kein Bau für Windows (config.w32) oder macOS; PHP 8.2 und 8.4 nicht gebaut.
| Restzeile | Beschreibung | Stand |
|---|---|---|
D36.4c Rest aus D36.4b | (1) Verteilung: kein PECL-Paket (`package.xml`) und kein Bau für Windows (`config.w32`, SChannel) oder macOS (Secure Transport); geprüft nur Linux arm64 mit PHP 8.3 (8.2 und 8.4 nicht gebaut). (2) Nicht in der Erweiterung: `CharacterSet` (immer UTF-8), MARS, Windows- und Entra-Anmeldung, Always Encrypted. (3) Rollbare Cursor sind immer statisch und halten die Menge im Speicher; ein Strom gilt nur, solange die Anweisung auf seiner Spalte steht; bei PDO strömt nur die letzte gebundene LOB-Spalte. (4) Der Pool gilt je Prozess und kennt keine Einstellung der Grösse oder Ruhezeit (`php.ini`). (5) Die Werte von `SQLSRV_SQLTYPE_*`/`SQLSRV_PHPTYPE_*` sind eigene Kodierungen (Programme nutzen die Namen; wer die Zahlen speichert, merkt den Unterschied zu sqlsrv). (6) `PDO::PARAM_STR` geht als `nvarchar` und der Server wandelt in den deklarierten Typ (wie pdo_sqlsrv); Typen ausserhalb dessen, was SQL Server so wandelt, brauchen `CAST` im Text. **Erledigt 21.10.2026:** (1) PECL-Paket: `paket.sh` baut `ksql-<Fassung>.tgz` mit `package.xml` (von `pecl package-validate` geprüft) und dem Kern unter `kern/`; `config.m4` legt die Unterordner für den Bau ausserhalb der Quellen an (`PHP_ADD_BUILD_DIR`, sonst scheiterte `pecl install`). Der Prüfstand `php/pecl.Dockerfile` installiert das Paket in einem frischen PHP 8.2, 8.3 und 8.4 (Linux x64) und lädt es. Der Prüfstand `php/Dockerfile` nimmt die PHP-Fassung als Bauargument; `PhpPruefstandTests` spielt den Katalog jetzt mit PHP 8.2, 8.3 und 8.4 am KSQL-Port und mit 8.3 am Orakel ab, jeweils samt `merkmale.php` (Tabellenwerte, Cursor, Ströme, Pool; 0 Fehlschläge) - alles grün. `merkmale.php` nahm am KSQL-Port `0x01` (dort eine Ganzzahl) und umging `SUBSTRING` über `varbinary(max)` (behoben in D36.5d). Rest in D36.4d. | ✅ |
D36.4d Rest aus D36.4c | (1) Verteilung: kein Bau für Windows (`config.w32`, SChannel) oder macOS (Secure Transport); das PECL-Paket nur für den eigenen Gebrauch (Code bleibt geschlossen). (2) Nicht in der Erweiterung: `CharacterSet` (immer UTF-8), MARS, Windows- und Entra-Anmeldung, Always Encrypted. (3) Rollbare Cursor sind immer statisch und halten die Menge im Speicher; ein Strom gilt nur, solange die Anweisung auf seiner Spalte steht; bei PDO strömt nur die letzte gebundene LOB-Spalte. (4) Der Pool gilt je Prozess und kennt keine Einstellung der Grösse oder Ruhezeit (`php.ini`). (5) Die Werte von `SQLSRV_SQLTYPE_*`/`SQLSRV_PHPTYPE_*` sind eigene Kodierungen (Programme nutzen die Namen; wer die Zahlen speichert, merkt den Unterschied zu sqlsrv). (6) `PDO::PARAM_STR` geht als `nvarchar` und der Server wandelt in den deklarierten Typ (wie pdo_sqlsrv); Typen ausserhalb dessen, was SQL Server so wandelt, brauchen `CAST` im Text. | ⬜ |
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; fremd sind nur PHP und OpenSSL. Kein PECL-Paket.