@qualithm/arrow-flight-sql-js 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -50
- package/package.json +2 -1
- package/proto/Flight.proto +645 -0
- package/proto/FlightSql.proto +1925 -0
package/README.md
CHANGED
|
@@ -52,20 +52,27 @@ const client = new FlightSqlClient({
|
|
|
52
52
|
host: "localhost",
|
|
53
53
|
port: 31337,
|
|
54
54
|
tls: true,
|
|
55
|
-
token: "your-bearer-token"
|
|
55
|
+
auth: { type: "bearer", token: "your-bearer-token" }
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
+
// Connect to the server
|
|
59
|
+
await client.connect()
|
|
60
|
+
|
|
58
61
|
// Execute a query
|
|
59
|
-
const
|
|
62
|
+
const result = await client.query("SELECT * FROM my_table LIMIT 100")
|
|
60
63
|
|
|
61
64
|
// Process Arrow record batches
|
|
62
|
-
for await (const batch of stream) {
|
|
65
|
+
for await (const batch of result.stream()) {
|
|
63
66
|
console.log(`Received ${batch.numRows} rows`)
|
|
64
67
|
// batch is an Arrow RecordBatch
|
|
65
68
|
}
|
|
66
69
|
|
|
70
|
+
// Or collect all results into a table
|
|
71
|
+
const table = await result.collect()
|
|
72
|
+
console.log(`Total rows: ${table.numRows}`)
|
|
73
|
+
|
|
67
74
|
// Clean up
|
|
68
|
-
|
|
75
|
+
client.close()
|
|
69
76
|
```
|
|
70
77
|
|
|
71
78
|
## Connection Pooling
|
|
@@ -73,28 +80,41 @@ await client.close()
|
|
|
73
80
|
```typescript
|
|
74
81
|
import { FlightSqlPool } from "@qualithm/arrow-flight-sql-js"
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
83
|
+
// Create a pool with client and pool configuration
|
|
84
|
+
const pool = new FlightSqlPool(
|
|
85
|
+
// Client options
|
|
86
|
+
{
|
|
87
|
+
host: "localhost",
|
|
88
|
+
port: 31337,
|
|
89
|
+
tls: false,
|
|
90
|
+
auth: { type: "basic", username: "admin", password: "secret" }
|
|
91
|
+
},
|
|
92
|
+
// Pool options
|
|
93
|
+
{
|
|
94
|
+
minConnections: 2,
|
|
95
|
+
maxConnections: 10,
|
|
96
|
+
idleTimeoutMs: 30_000
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
// Initialize the pool (creates minConnections)
|
|
101
|
+
await pool.initialize()
|
|
84
102
|
|
|
85
103
|
// Acquire a client from the pool
|
|
86
104
|
const client = await pool.acquire()
|
|
87
105
|
try {
|
|
88
|
-
const
|
|
106
|
+
const result = await client.query("SELECT 1")
|
|
107
|
+
const table = await result.collect()
|
|
89
108
|
// ... process results
|
|
90
109
|
} finally {
|
|
91
110
|
// Return to pool
|
|
92
111
|
pool.release(client)
|
|
93
112
|
}
|
|
94
113
|
|
|
95
|
-
// Or use the convenience method
|
|
96
|
-
|
|
97
|
-
|
|
114
|
+
// Or use the convenience method (handles acquire/release automatically)
|
|
115
|
+
await pool.withConnection(async (client) => {
|
|
116
|
+
const result = await client.query("SELECT * FROM users")
|
|
117
|
+
return result.collect()
|
|
98
118
|
})
|
|
99
119
|
|
|
100
120
|
// Graceful shutdown
|
|
@@ -112,14 +132,14 @@ const client = new FlightSqlClient({
|
|
|
112
132
|
host: "localhost",
|
|
113
133
|
port: 31337,
|
|
114
134
|
tls: true,
|
|
115
|
-
token: "your-bearer-token"
|
|
135
|
+
auth: { type: "bearer", token: "your-bearer-token" }
|
|
116
136
|
})
|
|
117
137
|
|
|
118
138
|
await client.connect()
|
|
119
139
|
|
|
120
140
|
// Subscribe to real-time updates
|
|
121
141
|
const subscription = client.subscribe("SELECT * FROM events WHERE status = 'pending'", {
|
|
122
|
-
mode: SubscriptionMode.
|
|
142
|
+
mode: SubscriptionMode.ChangesOnly, // Full | ChangesOnly | Tail
|
|
123
143
|
heartbeatMs: 30_000 // Server heartbeat interval
|
|
124
144
|
})
|
|
125
145
|
|
|
@@ -130,7 +150,7 @@ for await (const batch of subscription) {
|
|
|
130
150
|
|
|
131
151
|
// Or with cancellation
|
|
132
152
|
const controller = new AbortController()
|
|
133
|
-
const
|
|
153
|
+
const cancelableSubscription = client.subscribe(query, {
|
|
134
154
|
signal: controller.signal,
|
|
135
155
|
autoReconnect: true,
|
|
136
156
|
maxReconnectAttempts: 10
|
|
@@ -140,20 +160,20 @@ const subscription = client.subscribe(query, {
|
|
|
140
160
|
controller.abort()
|
|
141
161
|
|
|
142
162
|
// Or manually unsubscribe
|
|
143
|
-
await
|
|
163
|
+
await cancelableSubscription.unsubscribe()
|
|
144
164
|
```
|
|
145
165
|
|
|
146
166
|
### Subscription Options
|
|
147
167
|
|
|
148
|
-
| Option | Default
|
|
149
|
-
| ---------------------- |
|
|
150
|
-
| `mode` | `
|
|
151
|
-
| `heartbeatMs` | `30000`
|
|
152
|
-
| `signal` | -
|
|
153
|
-
| `autoReconnect` | `true`
|
|
154
|
-
| `maxReconnectAttempts` | `10`
|
|
155
|
-
| `reconnectDelayMs` | `1000`
|
|
156
|
-
| `maxReconnectDelayMs` | `30000`
|
|
168
|
+
| Option | Default | Description |
|
|
169
|
+
| ---------------------- | ------------- | -------------------------------------------------- |
|
|
170
|
+
| `mode` | `ChangesOnly` | Subscription mode (Full, ChangesOnly, Tail) |
|
|
171
|
+
| `heartbeatMs` | `30000` | Server heartbeat interval in milliseconds |
|
|
172
|
+
| `signal` | - | AbortSignal for cancellation |
|
|
173
|
+
| `autoReconnect` | `true` | Auto-reconnect on connection loss |
|
|
174
|
+
| `maxReconnectAttempts` | `10` | Maximum reconnection attempts |
|
|
175
|
+
| `reconnectDelayMs` | `1000` | Initial reconnect delay |
|
|
176
|
+
| `maxReconnectDelayMs` | `30000` | Maximum reconnect delay (with exponential backoff) |
|
|
157
177
|
|
|
158
178
|
### Low-Level DoExchange
|
|
159
179
|
|
|
@@ -198,6 +218,8 @@ import {
|
|
|
198
218
|
const client = new FlightSqlClient({
|
|
199
219
|
host: "localhost",
|
|
200
220
|
port: 31337,
|
|
221
|
+
tls: false,
|
|
222
|
+
auth: { type: "none" },
|
|
201
223
|
metrics: new ConsoleMetricsHandler()
|
|
202
224
|
})
|
|
203
225
|
// Output: [FlightSQL Metrics] ✓ query success (42ms)
|
|
@@ -207,11 +229,15 @@ const metricsHandler = new InMemoryMetricsHandler()
|
|
|
207
229
|
const testClient = new FlightSqlClient({
|
|
208
230
|
host: "localhost",
|
|
209
231
|
port: 31337,
|
|
232
|
+
tls: false,
|
|
233
|
+
auth: { type: "none" },
|
|
210
234
|
metrics: metricsHandler
|
|
211
235
|
})
|
|
212
236
|
|
|
213
237
|
// Query metrics after operations
|
|
214
|
-
await testClient.
|
|
238
|
+
await testClient.connect()
|
|
239
|
+
const result = await testClient.query("SELECT 1")
|
|
240
|
+
await result.collect()
|
|
215
241
|
console.log(metricsHandler.getAverageDuration("query"))
|
|
216
242
|
console.log(metricsHandler.getErrorRate("query"))
|
|
217
243
|
console.log(metricsHandler.getSummary())
|
|
@@ -261,7 +287,8 @@ import {
|
|
|
261
287
|
} from "@qualithm/arrow-flight-sql-js"
|
|
262
288
|
|
|
263
289
|
try {
|
|
264
|
-
await client.
|
|
290
|
+
const result = await client.query("SELECT * FROM missing_table")
|
|
291
|
+
await result.collect()
|
|
265
292
|
} catch (error) {
|
|
266
293
|
if (error instanceof QueryError) {
|
|
267
294
|
console.error("SQL Error:", error.message)
|
|
@@ -285,6 +312,8 @@ import { FlightSqlClient, RetryPolicy, retryPolicies } from "@qualithm/arrow-fli
|
|
|
285
312
|
const client = new FlightSqlClient({
|
|
286
313
|
host: "localhost",
|
|
287
314
|
port: 31337,
|
|
315
|
+
tls: false,
|
|
316
|
+
auth: { type: "bearer", token: "my-token" },
|
|
288
317
|
retry: retryPolicies.default // 3 retries, exponential backoff
|
|
289
318
|
})
|
|
290
319
|
|
|
@@ -311,6 +340,8 @@ const customPolicy = new RetryPolicy({
|
|
|
311
340
|
const clientWithCustomRetry = new FlightSqlClient({
|
|
312
341
|
host: "localhost",
|
|
313
342
|
port: 31337,
|
|
343
|
+
tls: false,
|
|
344
|
+
auth: { type: "bearer", token: "my-token" },
|
|
314
345
|
retry: customPolicy
|
|
315
346
|
})
|
|
316
347
|
```
|
|
@@ -360,16 +391,15 @@ Use prepared statements for parameterized queries:
|
|
|
360
391
|
const stmt = await client.prepare("SELECT * FROM users WHERE id = ? AND status = ?")
|
|
361
392
|
|
|
362
393
|
try {
|
|
363
|
-
//
|
|
364
|
-
const
|
|
394
|
+
// Execute the query (returns a QueryResult)
|
|
395
|
+
const result = await stmt.executeQuery()
|
|
365
396
|
|
|
366
|
-
for await (const batch of stream) {
|
|
397
|
+
for await (const batch of result.stream()) {
|
|
367
398
|
console.log(`Received ${batch.numRows} rows`)
|
|
368
399
|
}
|
|
369
400
|
|
|
370
|
-
//
|
|
371
|
-
const
|
|
372
|
-
// ...
|
|
401
|
+
// Or collect all results
|
|
402
|
+
const table = await result.collect()
|
|
373
403
|
} finally {
|
|
374
404
|
// Always close prepared statements
|
|
375
405
|
await stmt.close()
|
|
@@ -384,23 +414,35 @@ The main client for interacting with Flight SQL servers.
|
|
|
384
414
|
|
|
385
415
|
#### Constructor Options
|
|
386
416
|
|
|
387
|
-
| Option
|
|
388
|
-
|
|
|
389
|
-
| `host`
|
|
390
|
-
| `port`
|
|
391
|
-
| `tls`
|
|
392
|
-
| `
|
|
393
|
-
| `
|
|
394
|
-
| `
|
|
395
|
-
| `
|
|
396
|
-
| `
|
|
417
|
+
| Option | Type | Default | Description |
|
|
418
|
+
| ------------------ | ------------------------ | ------- | ------------------------------- |
|
|
419
|
+
| `host` | `string` | — | Server hostname |
|
|
420
|
+
| `port` | `number` | — | Server port |
|
|
421
|
+
| `tls` | `boolean` | `true` | Enable TLS |
|
|
422
|
+
| `auth` | `AuthConfig` | — | Authentication configuration |
|
|
423
|
+
| `credentials` | `ChannelCredentials` | — | Custom gRPC channel credentials |
|
|
424
|
+
| `metadata` | `Record<string, string>` | — | Custom metadata headers |
|
|
425
|
+
| `connectTimeoutMs` | `number` | `30000` | Connection timeout in ms |
|
|
426
|
+
| `requestTimeoutMs` | `number` | `60000` | Request timeout in ms |
|
|
427
|
+
|
|
428
|
+
##### AuthConfig
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
type AuthConfig =
|
|
432
|
+
| { type: "bearer"; token: string }
|
|
433
|
+
| { type: "basic"; username: string; password: string }
|
|
434
|
+
| { type: "none" }
|
|
435
|
+
```
|
|
397
436
|
|
|
398
437
|
#### Methods
|
|
399
438
|
|
|
400
439
|
##### Query Execution
|
|
401
440
|
|
|
402
|
-
- `
|
|
403
|
-
|
|
441
|
+
- `query(query: string, options?): Promise<QueryResult>` – Execute SQL, returns result with
|
|
442
|
+
`stream()` and `collect()` methods
|
|
443
|
+
- `execute(query: string, options?): Promise<FlightInfo>` – _(deprecated)_ Execute SQL, return
|
|
444
|
+
flight info
|
|
445
|
+
- `executeUpdate(query: string): Promise<bigint>` – Execute DML, return affected rows
|
|
404
446
|
- `prepare(query: string): Promise<PreparedStatement>` – Create prepared statement
|
|
405
447
|
|
|
406
448
|
##### Catalog Introspection
|
|
@@ -422,7 +464,8 @@ The main client for interacting with Flight SQL servers.
|
|
|
422
464
|
|
|
423
465
|
##### Connection Management
|
|
424
466
|
|
|
425
|
-
- `
|
|
467
|
+
- `connect(): Promise<void>` – Establish connection and authenticate
|
|
468
|
+
- `close(): void` – Close connection and release resources
|
|
426
469
|
- `isConnected(): boolean` – Check connection status
|
|
427
470
|
|
|
428
471
|
## Architecture
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qualithm/arrow-flight-sql-js",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Arrow Flight SQL client for JavaScript and TypeScript runtimes.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"test:integration": "bun test src/__tests__/integration",
|
|
60
60
|
"test:unit": "bun test src/__tests__/unit",
|
|
61
61
|
"test:watch": "bun test --watch",
|
|
62
|
+
"typecheck": "tsc -p tsconfig.node.json --noEmit",
|
|
62
63
|
"bench": "bun run benchmarks/index.ts"
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|