You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> **No other Swift SQL library offers this.**`queryJsonStream()` is the breakthrough feature that makes CosmoSQLClient unique.
85
+
86
+
### The Problem with Large JSON Results
87
+
88
+
When SQL Server executes `SELECT ... FOR JSON PATH`, it fragments the output at ~2033-character boundaries that **do not align with JSON object boundaries**. A single JSON object may be split across multiple network packets:
89
+
90
+
```
91
+
Packet 1: [{"Id":1,"Name":"Alice","Desc":"A long descrip
92
+
Packet 2: tion that spans packets"},{"Id":2,"Name":"Bob"...
93
+
```
94
+
95
+
Traditional approaches buffer the **entire result** before any processing begins — wasting memory and delaying first-byte delivery. Microsoft's own `IAsyncEnumerable` has this same limitation for JSON.
96
+
97
+
### The Solution: `queryJsonStream()`
98
+
99
+
`queryJsonStream()` uses a pure Swift `JSONChunkAssembler` state machine that detects exact `{...}` object boundaries across arbitrary chunk splits — including splits mid-string with escape sequences. Each complete JSON object is yielded **immediately** when its closing `}` arrives.
100
+
101
+
```swift
102
+
importCosmoMSSQL
103
+
104
+
// Yields one Data chunk per JSON object — never buffers the full array
105
+
fortryawait chunk in conn.queryJsonStream(
106
+
"SELECT Id, Name, Price FROM Products FOR JSON PATH") {
107
+
let obj =try JSONSerialization.jsonObject(with: chunk)
108
+
print(obj)
109
+
}
110
+
```
111
+
112
+
### Strongly-Typed JSON Streaming
113
+
114
+
Decode directly into your `Decodable` model, one object at a time:
115
+
116
+
```swift
117
+
structProduct: Decodable {
118
+
let Id: Int
119
+
let Name: String
120
+
let Price: Double
121
+
}
122
+
123
+
fortryawait product in conn.queryJsonStream(
124
+
"SELECT Id, Name, Price FROM Products FOR JSON PATH",
125
+
as: Product.self) {
126
+
// Each product is fully decoded before the next one arrives
Stream raw result rows without buffering the full result set:
134
+
135
+
```swift
136
+
fortryawait row in conn.queryStream(
137
+
"SELECT * FROM LargeTable WHERE active = @p1", [.bool(true)]) {
138
+
let id = row["id"].asInt32()!
139
+
let name = row["name"].asString()!
140
+
// process one row at a time
141
+
}
142
+
```
143
+
144
+
### Available on All Three Databases
145
+
146
+
JSON streaming works identically on SQL Server, PostgreSQL, and MySQL:
147
+
148
+
```swift
149
+
// SQL Server — FOR JSON PATH
150
+
fortryawait obj in mssqlConn.queryJsonStream(
151
+
"SELECT id, name FROM Departments FOR JSON PATH") { ... }
152
+
153
+
// PostgreSQL — row_to_json
154
+
fortryawait obj in pgConn.queryJsonStream(
155
+
"SELECT row_to_json(t) FROM (SELECT id, name FROM departments) t") { ... }
156
+
157
+
// MySQL — JSON_OBJECT
158
+
fortryawait obj in mysqlConn.queryJsonStream(
159
+
"SELECT JSON_OBJECT('id', id, 'name', name) FROM departments") { ... }
160
+
```
161
+
162
+
All three pool types (`MSSQLConnectionPool`, `PostgresConnectionPool`, `MySQLConnectionPool`) expose the same streaming methods with automatic connection acquire/release and cancellation support.
74
163
75
164
---
76
165
@@ -1080,18 +1169,88 @@ swift test
1080
1169
1081
1170
## Benchmarks
1082
1171
1083
-
> CosmoSQLClient (NIO) vs SQLClient-Swift (FreeTDS) · macOS · Apple Silicon · MSSQL Server 2019
> - JSON streaming: **No competitor offers this feature at all**
1251
+
> - Warm query gap on MySQL/Postgres: mature competitors have years of binary-protocol micro-optimisation — an expected trade-off for a pure-Swift/NIO implementation
1252
+
1253
+
Run the benchmarks yourself — see [`cosmo-benchmark/`](cosmo-benchmark/) for Swift, and [`Benchmarks/`](https://github.com/vkuttyp/CosmoSQLClient-Dotnet/tree/main/Benchmarks) for the .NET port.
0 commit comments