@oxy-hq/sdk 2.13.0 → 2.16.0

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.
Files changed (44) hide show
  1. package/README.md +67 -0
  2. package/dist/{function-context-D8eyZuw_.d.cts → function-context-BNpL5bFb.d.cts} +223 -20
  3. package/dist/function-context-BNpL5bFb.d.cts.map +1 -0
  4. package/dist/{function-context-D8eyZuw_.d.mts → function-context-BNpL5bFb.d.mts} +223 -20
  5. package/dist/function-context-BNpL5bFb.d.mts.map +1 -0
  6. package/dist/index.cjs +19 -16
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +3 -3
  9. package/dist/index.d.cts.map +1 -1
  10. package/dist/index.d.mts +3 -3
  11. package/dist/index.d.mts.map +1 -1
  12. package/dist/index.mjs +17 -15
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/ops.d.cts +1 -1
  15. package/dist/ops.d.mts +1 -1
  16. package/dist/{react-D-Sf973d.d.mts → react-CljeXJuw.d.cts} +56 -7
  17. package/dist/react-CljeXJuw.d.cts.map +1 -0
  18. package/dist/{react-D-Sf973d.d.cts → react-CljeXJuw.d.mts} +56 -7
  19. package/dist/react-CljeXJuw.d.mts.map +1 -0
  20. package/dist/{react-CkAQg9wB.cjs → react-Dvkv2deI.cjs} +46 -55
  21. package/dist/react-Dvkv2deI.cjs.map +1 -0
  22. package/dist/{react-Cq3xULOr.mjs → react-OW1t_J0M.mjs} +39 -22
  23. package/dist/react-OW1t_J0M.mjs.map +1 -0
  24. package/dist/rolldown-runtime-KC0qvQup.cjs +34 -0
  25. package/dist/shell.cjs +4 -3
  26. package/dist/shell.cjs.map +1 -1
  27. package/dist/shell.d.cts +2 -2
  28. package/dist/shell.d.mts +2 -2
  29. package/dist/shell.mjs +1 -1
  30. package/dist/testing.cjs +4431 -0
  31. package/dist/testing.cjs.map +1 -0
  32. package/dist/testing.d.cts +656 -0
  33. package/dist/testing.d.cts.map +1 -0
  34. package/dist/testing.d.mts +656 -0
  35. package/dist/testing.d.mts.map +1 -0
  36. package/dist/testing.mjs +4395 -0
  37. package/dist/testing.mjs.map +1 -0
  38. package/package.json +22 -9
  39. package/dist/function-context-D8eyZuw_.d.cts.map +0 -1
  40. package/dist/function-context-D8eyZuw_.d.mts.map +0 -1
  41. package/dist/react-CkAQg9wB.cjs.map +0 -1
  42. package/dist/react-Cq3xULOr.mjs.map +0 -1
  43. package/dist/react-D-Sf973d.d.cts.map +0 -1
  44. package/dist/react-D-Sf973d.d.mts.map +0 -1
@@ -0,0 +1,4431 @@
1
+ // @oxy/sdk - TypeScript SDK for Oxy data platform
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
+ const require_rolldown_runtime = require('./rolldown-runtime-KC0qvQup.cjs');
4
+ let node_crypto = require("node:crypto");
5
+ node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
6
+
7
+ //#region src/testing/host-contract.ts
8
+ /**
9
+ * The host's words, gates, op names and rules, as `@oxy-hq/sdk/testing`
10
+ * enforces them on an app's unit tests.
11
+ *
12
+ * ONE SOURCE OF TRUTH, AND IT IS NOT THIS FILE. Every string below is quoted
13
+ * from the host's source — `host.rs`, `host/destinations.rs`,
14
+ * `host/airhouse_ops.rs`, `upsert_support.rs`, `tx.rs`, `runtime.rs` under
15
+ * `crates/app/src/server/api/custom_apps_functions/`, and the connector's
16
+ * `transaction.rs` / `postgres_tx/convert.rs` — never paraphrased.
17
+ * `{placeholder}`s stand for what the host formats in (`{database}`,
18
+ * `{dialect}`, …) and use the host's own names.
19
+ *
20
+ * HELD TO THE HOST BY A RUST TEST. `sdk_testing_drift.rs`, beside `host.rs`,
21
+ * `include_str!`s this file and fails when a `refusal:` here is no longer a
22
+ * sentence its `source:` file contains, when `HOST_OPS` differs from the
23
+ * host's closed list, when `GATES` stops naming exactly the fields of
24
+ * `FunctionCapabilities`, when `ABSENT_GLOBALS` differs from `oxyc`'s lint
25
+ * list, or when `FETCH_RULES` differs from `is_safe_outbound`. One direction
26
+ * only: this file is checked against the host, the host is never checked
27
+ * against this file (`internal-docs/sdk-testing-context.md` §7, answer 9).
28
+ *
29
+ * THE RUST TEST READS TEXT, NOT TYPESCRIPT: after stripping comments it takes
30
+ * the block from `export const HOST_OPS` to `] as const;`, every object whose
31
+ * key line ends `: {` and carries `source:` and `refusal:` lines, the
32
+ * `hostField:` / `ops:` lines of `GATES`, the `name:` / `member:` lines of
33
+ * `ABSENT_GLOBALS`, and every quoted string in `FETCH_RULES`. Keep those keys
34
+ * spelled as they are, each `refusal:` a single string literal, and none of
35
+ * them behind a comment that is not a full-line one.
36
+ *
37
+ * NO `contractVersion` (§7, answer 10): a reworded refusal reaches an app on
38
+ * its next SDK bump, which is the right moment to see it; a version field
39
+ * with no consumer is a mechanism nobody reads.
40
+ */
41
+ /**
42
+ * Every name the host pages an op under — `HOST_OPS` in `host_call_attrs.rs`,
43
+ * "pinned by unit tests to `host_op_name` and `runtime::host_call_span`". The
44
+ * `HostOp` type is this list, so `"warehouse.inserts"` does not compile.
45
+ */
46
+ const HOST_OPS = [
47
+ "query",
48
+ "query_stream",
49
+ "fetch",
50
+ "semantic.query",
51
+ "airway.run",
52
+ "warehouse.insert",
53
+ "warehouse.exec",
54
+ "warehouse.upsert",
55
+ "warehouse.query",
56
+ "tx.begin",
57
+ "tx.begin_oltp",
58
+ "tx.query",
59
+ "tx.exec",
60
+ "tx.commit",
61
+ "tx.rollback",
62
+ "oltp.query",
63
+ "oltp.exec",
64
+ "airhouse.query",
65
+ "airhouse.exec",
66
+ "airhouse.append",
67
+ "storage.getUploadUrl",
68
+ "storage.getDownloadUrl",
69
+ "storage.put",
70
+ "storage.get",
71
+ "storage.head",
72
+ "storage.list",
73
+ "storage.delete",
74
+ "storage.copy",
75
+ "secrets.set",
76
+ "email.send",
77
+ "org.people",
78
+ "org.places",
79
+ "org.assignments"
80
+ ];
81
+ /**
82
+ * The surface `reply_json` prefixes a refusal with (`runtime.rs`): a thrown
83
+ * `HostError`'s message is `"<surface>: <host message>"`. Every `tx.*` verb —
84
+ * `begin_oltp` included — answers under `ctx.tx`, because one op carries all
85
+ * six.
86
+ */
87
+ const SURFACES = {
88
+ query: "ctx.query",
89
+ queryStream: "ctx.queryStream",
90
+ fetch: "ctx.fetch",
91
+ warehouse: "ctx.warehouse",
92
+ tx: "ctx.tx",
93
+ oltp: "ctx.oltp",
94
+ airhouse: "ctx.airhouse",
95
+ secretsSet: "ctx.secrets.set",
96
+ emailSend: "ctx.email.send",
97
+ storage: "ctx.storage",
98
+ orgPeople: "ctx.org.people",
99
+ orgPlaces: "ctx.org.places",
100
+ orgAssignments: "ctx.org.assignments",
101
+ semanticQuery: "ctx.semantic.query",
102
+ airwayRun: "ctx.airway.run"
103
+ };
104
+ /**
105
+ * Every refusal the context throws, quoted from the host. The context renders
106
+ * a template by substituting its `{placeholder}`s and prefixing the surface.
107
+ */
108
+ const REFUSALS = {
109
+ secretsWrite: {
110
+ source: "host.rs",
111
+ refusal: "ctx.secrets.set: this function has not declared the `secrets.write` capability (add it to oxy-app.json to permit writes)"
112
+ },
113
+ emailSend: {
114
+ source: "host.rs",
115
+ refusal: "EmailCapabilityMissing: this function has not declared the `email.send` capability (add \"email\": { \"send\": true } to its oxy-app.json entry)"
116
+ },
117
+ orgPeople: {
118
+ source: "host.rs",
119
+ refusal: "OrgCapabilityMissing: this function has not declared the `org.read` capability (add \"org\": { \"read\": true } to its oxy-app.json entry)"
120
+ },
121
+ orgMember: {
122
+ source: "host.rs",
123
+ refusal: "OrgCapabilityMissing: this function has not declared the `org.read` capability (add \"org\": { \"read\": true } to its oxy-app.json entry) — ctx.org.{member}"
124
+ },
125
+ storageWrite: {
126
+ source: "host.rs",
127
+ refusal: "StorageCapabilityMissing: this function has not declared the `storage.write` capability (add \"storage\": { \"write\": true } to its oxy-app.json entry)"
128
+ },
129
+ storageRead: {
130
+ source: "host.rs",
131
+ refusal: "StorageCapabilityMissing: this function has not declared the `storage.read` capability (add \"storage\": { \"read\": true } to its oxy-app.json entry)"
132
+ },
133
+ oltp: {
134
+ source: "host.rs",
135
+ refusal: "OltpCapabilityMissing: this function has not declared the `oltp` capability (add \"oltp\": { \"enabled\": true } to its oxy-app.json entry). The schema it writes is derived from the app's own slug — the manifest only enables access."
136
+ },
137
+ airhouse: {
138
+ source: "host/airhouse_ops.rs",
139
+ refusal: "AirhouseCapabilityMissing: this function has not declared the `airhouse` capability (add \"airhouse\": { \"enabled\": true } to its oxy-app.json entry). The schema it writes is derived from the app's own slug — the manifest only enables access."
140
+ },
141
+ destinationNotDeclared: {
142
+ source: "host.rs",
143
+ refusal: "database '{database}' is not in this function's `destinations` allowlist (declare it in oxy-app.json to permit writes)"
144
+ },
145
+ databaseNotConfigured: {
146
+ source: "host.rs",
147
+ refusal: "database '{database}' is not configured for this project"
148
+ },
149
+ managedOltpWrite: {
150
+ source: "host/destinations.rs",
151
+ refusal: "database '{database}' is the org's OLTP store, which this surface reaches as the read-only analyst — write this app's own records with ctx.oltp"
152
+ },
153
+ customerWarehouseWrite: {
154
+ source: "host/destinations.rs",
155
+ refusal: "database '{database}' is a customer warehouse, and customer warehouses are read-only to apps. Facts this app records belong in Airhouse (ctx.airhouse); records it edits belong in ctx.oltp. If this write has to stay, say why on the function in oxy-app.json: \"customerWarehouseWrites\": { \"{database}\": \"<reason>\" }"
156
+ },
157
+ customerWarehouseTransaction: {
158
+ source: "host/destinations.rs",
159
+ refusal: ". A ctx.tx transaction counts as a write even when it only reads — read with ctx.warehouse.query instead"
160
+ },
161
+ upsertUnsupported: {
162
+ source: "upsert_support.rs",
163
+ refusal: "warehouse.upsert is not supported on {dialect}: it compiles to `INSERT … ON CONFLICT … DO UPDATE`, which only Postgres and DuckDB parse. Use warehouse.insert, or warehouse.exec with this warehouse's own upsert statement."
164
+ },
165
+ transactionOpen: {
166
+ source: "host.rs",
167
+ refusal: "could not open a transaction on '{database}': {e}"
168
+ },
169
+ transactionUnsupported: {
170
+ source: "transaction.rs",
171
+ refusal: "{backend} does not support multi-statement transactions — ctx.tx() requires a Postgres-backed database (`type: postgres`). Use ctx.warehouse.{insert,exec,upsert} for single-statement writes."
172
+ },
173
+ transactionsOpen: {
174
+ source: "tx.rs",
175
+ refusal: "this invocation already has {MAX_OPEN} transactions open. Commit or roll one back before opening another."
176
+ },
177
+ transactionFinished: {
178
+ source: "runtime.rs",
179
+ refusal: "{label}: this transaction is already finished — {what} was called after the callback returned"
180
+ },
181
+ transactionFnNotFunction: {
182
+ source: "runtime.rs",
183
+ refusal: "{signature}: fn must be a function"
184
+ },
185
+ btoaBytes: {
186
+ source: "runtime.rs",
187
+ refusal: "btoa: expected a string. For bytes use bytesToBase64() from @oxy-hq/sdk"
188
+ },
189
+ atobPadding: {
190
+ source: "runtime.rs",
191
+ refusal: "atob: '=' may only appear as trailing padding"
192
+ },
193
+ atobLength: {
194
+ source: "runtime.rs",
195
+ refusal: "atob: invalid base64 length"
196
+ },
197
+ fetchInvalidUrl: {
198
+ source: "host.rs",
199
+ refusal: "invalid url: {e}"
200
+ },
201
+ fetchBlocked: {
202
+ source: "host.rs",
203
+ refusal: "fetch to '{url}' blocked by SSRF allowlist"
204
+ },
205
+ fetchInvalidHeaderName: {
206
+ source: "host.rs",
207
+ refusal: "InvalidFetchHeader: `{k}` is not a header name"
208
+ },
209
+ fetchInvalidHeaderValue: {
210
+ source: "host.rs",
211
+ refusal: "InvalidFetchHeader: the value of `{k}` is not a header value"
212
+ },
213
+ fetchTooLarge: {
214
+ source: "host.rs",
215
+ refusal: "response too large ({len} bytes > {max_bytes} cap)"
216
+ },
217
+ slugCannotBackASchema: {
218
+ source: "host.rs",
219
+ refusal: "the capability is enabled, but this app's slug '{slug}' cannot back an {store} schema: to do so a slug must start with a letter, be at most {max} characters, and use only lowercase letters, digits and hyphens (a `_` is refused — it would collide with the hyphenated form). A leading digit is a legal app slug but not a legal schema name. Rename the app to one that qualifies."
220
+ },
221
+ oltpParamsNotArray: {
222
+ source: "host.rs",
223
+ refusal: "`params` must be an array of values. Pass positional arguments for $1, $2, … — e.g. [name, partySize]."
224
+ },
225
+ noDefaultDatabase: {
226
+ source: "host.rs",
227
+ refusal: "this project has no databases configured"
228
+ },
229
+ oltpUnsupportedColumn: {
230
+ source: "postgres_tx/convert.rs",
231
+ refusal: "result column `{name}` has Postgres type `{ty}`, which cannot be returned directly. Cast it to text in the SELECT list and parse it in your function — cast the whole expression, not the output name (`avg(qty)::text`, `amount::text`). Note `avg`/`sum` over any numeric type, and a bare decimal literal, are all `numeric`. (Supported as-is: bool, int2/4/8, float4/8, text/varchar/char/name, json/jsonb, uuid, timestamptz/timestamp, date, time.)"
232
+ }
233
+ };
234
+ /**
235
+ * Every gate in `FunctionCapabilities`, in the struct's order. `storage_read`
236
+ * and `storage_write` list `check_storage_capability`'s arms (`copy` needs
237
+ * both); `customer_warehouse_writes` is decided per database by
238
+ * `destination_write_policy`, after the `destinations` allowlist.
239
+ * `storage_retention` and `fetch_max_bytes` are fields of the struct and
240
+ * deliberately absent: they shape an allowed call, they never refuse one.
241
+ */
242
+ const GATES = [
243
+ {
244
+ hostField: "secrets_write",
245
+ manifest: "secrets.write",
246
+ ops: ["secrets.set"]
247
+ },
248
+ {
249
+ hostField: "email_send",
250
+ manifest: "email.send",
251
+ ops: ["email.send"]
252
+ },
253
+ {
254
+ hostField: "org_read",
255
+ manifest: "org.read",
256
+ ops: [
257
+ "org.people",
258
+ "org.places",
259
+ "org.assignments"
260
+ ]
261
+ },
262
+ {
263
+ hostField: "storage_read",
264
+ manifest: "storage.read",
265
+ ops: [
266
+ "storage.getDownloadUrl",
267
+ "storage.get",
268
+ "storage.head",
269
+ "storage.list",
270
+ "storage.copy"
271
+ ]
272
+ },
273
+ {
274
+ hostField: "storage_write",
275
+ manifest: "storage.write",
276
+ ops: [
277
+ "storage.getUploadUrl",
278
+ "storage.put",
279
+ "storage.delete",
280
+ "storage.copy"
281
+ ]
282
+ },
283
+ {
284
+ hostField: "oltp",
285
+ manifest: "oltp.enabled",
286
+ ops: [
287
+ "oltp.query",
288
+ "oltp.exec",
289
+ "tx.begin_oltp"
290
+ ]
291
+ },
292
+ {
293
+ hostField: "airhouse",
294
+ manifest: "airhouse.enabled",
295
+ ops: [
296
+ "airhouse.query",
297
+ "airhouse.exec",
298
+ "airhouse.append"
299
+ ]
300
+ },
301
+ {
302
+ hostField: "customer_warehouse_writes",
303
+ manifest: "customerWarehouseWrites",
304
+ ops: [
305
+ "warehouse.insert",
306
+ "warehouse.exec",
307
+ "warehouse.upsert",
308
+ "tx.begin"
309
+ ]
310
+ }
311
+ ];
312
+ /**
313
+ * The globals the isolate does not define, as `oxyc`'s `isolate-global` lint
314
+ * names them (`ABSENT_GLOBALS` in `sdk/cli/src/publish/function-lint.ts`).
315
+ * `member` narrows an entry to `<name>.<member>`; an empty `member` is the
316
+ * whole of `process.*`. The isolate's bootstrap defines `Response`, `btoa`,
317
+ * `atob`, `console` and `__buildCtx` and nothing else (`runtime.rs`), so it has
318
+ * no `crypto` global at all; the lint singles out `subtle` because that is what
319
+ * an author reaches for, and `run()` removes the whole global as production
320
+ * does.
321
+ */
322
+ const ABSENT_GLOBALS = [
323
+ { name: "Buffer" },
324
+ { name: "TextEncoder" },
325
+ { name: "TextDecoder" },
326
+ { name: "Blob" },
327
+ { name: "File" },
328
+ { name: "FormData" },
329
+ {
330
+ name: "crypto",
331
+ member: "subtle"
332
+ },
333
+ {
334
+ name: "process",
335
+ member: ""
336
+ }
337
+ ];
338
+ /**
339
+ * `is_safe_outbound` in `host.rs`, the first-layer check every `ctx.fetch`
340
+ * URL meets before anything is sent: the scheme, the host names refused by
341
+ * name, and the suffixes an internal name ends with. The IP rules (loopback,
342
+ * unspecified, private, link-local, broadcast, documentation, v4-mapped and
343
+ * embedded v6) are code, in `fetch-rules.ts`. What no unit test can reproduce
344
+ * is the second layer — a public name that RESOLVES to a private address is
345
+ * caught at connect time by `PublicOnlyDnsResolver` — so the context does not
346
+ * pretend to.
347
+ */
348
+ const FETCH_RULES = {
349
+ scheme: "https",
350
+ literalHosts: [
351
+ "localhost",
352
+ "ip6-localhost",
353
+ "ip6-loopback"
354
+ ],
355
+ internalSuffixes: [
356
+ ".internal",
357
+ ".local",
358
+ ".localdomain",
359
+ ".svc",
360
+ ".cluster.local"
361
+ ]
362
+ };
363
+ /** `FETCH_MAX_BYTES` in `host.rs`: the default `ctx.fetch` response ceiling. */
364
+ const FETCH_MAX_BYTES = 10485760;
365
+ /** `MAX_OPEN` in `tx.rs`: transactions one invocation may hold open at once. */
366
+ const MAX_OPEN_TRANSACTIONS = 4;
367
+ /**
368
+ * How each dialect names itself in a refusal — `SqlDialect::as_str` in the
369
+ * connector crate, which `upsert_support::check` and `transaction::unsupported`
370
+ * format in. Only Postgres, DuckDB and SQLite parse `ON CONFLICT`
371
+ * (`parses_on_conflict`), and only the Postgres connector opens a transaction.
372
+ */
373
+ const DIALECTS = {
374
+ clickhouse: {
375
+ name: "ClickHouse",
376
+ parsesOnConflict: false,
377
+ opensTransactions: false
378
+ },
379
+ postgres: {
380
+ name: "PostgreSQL",
381
+ parsesOnConflict: true,
382
+ opensTransactions: true
383
+ },
384
+ duckdb: {
385
+ name: "DuckDB",
386
+ parsesOnConflict: true,
387
+ opensTransactions: false
388
+ }
389
+ };
390
+
391
+ //#endregion
392
+ //#region src/testing/fetch-rules.ts
393
+ /** The host's verdict on a URL: allowed, or refused before sending. */
394
+ function isSafeOutbound(url) {
395
+ if (url.protocol !== `${FETCH_RULES.scheme}:`) return false;
396
+ const host = url.hostname;
397
+ if (host === "") return false;
398
+ const ip = parseIp(host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host);
399
+ if (ip) return isPublicIp(ip);
400
+ const lower = host.toLowerCase();
401
+ if (FETCH_RULES.literalHosts.includes(lower)) return false;
402
+ return !FETCH_RULES.internalSuffixes.some((suffix) => lower.endsWith(suffix));
403
+ }
404
+ /** A literal IPv4 or IPv6 address, or `null` when `s` is a name. */
405
+ function parseIp(s) {
406
+ const v4 = parseV4(s);
407
+ if (v4) return { v4 };
408
+ const v6 = parseV6(s);
409
+ return v6 ? { v6 } : null;
410
+ }
411
+ function parseV4(s) {
412
+ const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(s);
413
+ if (!m) return null;
414
+ const parts = m.slice(1).map(Number);
415
+ if (parts.some((p) => p > 255)) return null;
416
+ return parts;
417
+ }
418
+ /** Eight 16-bit segments, or `null`. Accepts `::`, and a dotted v4 tail. */
419
+ function parseV6(s) {
420
+ if (!s.includes(":")) return null;
421
+ const zone = s.indexOf("%");
422
+ const halves = (zone >= 0 ? s.slice(0, zone) : s).split("::");
423
+ if (halves.length > 2) return null;
424
+ const head = halves[0] === "" ? [] : halves[0].split(":");
425
+ const tail = halves.length === 2 && halves[1] !== "" ? halves[1].split(":") : [];
426
+ const words = (groups) => {
427
+ const out = [];
428
+ for (const [i, g] of groups.entries()) if (g.includes(".")) {
429
+ if (i !== groups.length - 1) return null;
430
+ const v4 = parseV4(g);
431
+ if (!v4) return null;
432
+ out.push(v4[0] << 8 | v4[1], v4[2] << 8 | v4[3]);
433
+ } else {
434
+ if (!/^[0-9a-fA-F]{1,4}$/.test(g)) return null;
435
+ out.push(Number.parseInt(g, 16));
436
+ }
437
+ return out;
438
+ };
439
+ const h = words(head);
440
+ const t = words(tail);
441
+ if (!h || !t) return null;
442
+ if (halves.length === 1) return h.length === 8 ? h : null;
443
+ const fill = 8 - h.length - t.length;
444
+ if (fill < 1) return null;
445
+ return [
446
+ ...h,
447
+ ...new Array(fill).fill(0),
448
+ ...t
449
+ ];
450
+ }
451
+ /** `is_public_ip` in `host.rs`. */
452
+ function isPublicIp(ip) {
453
+ const canonical = "v6" in ip ? mappedV4(ip.v6) ?? ip : ip;
454
+ if ("v4" in canonical) return isPublicV4(canonical.v4);
455
+ const seg = canonical.v6;
456
+ if (seg.every((w) => w === 0)) return false;
457
+ if (seg.slice(0, 7).every((w) => w === 0) && seg[7] === 1) return false;
458
+ const embedded = embeddedV4(seg);
459
+ if (embedded) return isPublicV4(embedded);
460
+ const first = seg[0];
461
+ const linkLocal = (first & 65472) === 65152;
462
+ const uniqueLocal = (first & 65024) === 64512;
463
+ return !linkLocal && !uniqueLocal;
464
+ }
465
+ function isPublicV4([a, b, c, d]) {
466
+ if (a === 127) return false;
467
+ if (a === 0 && b === 0 && c === 0 && d === 0) return false;
468
+ return !(a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168) && !(a === 169 && b === 254) && !(a === 255 && b === 255 && c === 255 && d === 255) && !(a === 192 && b === 0 && c === 2 || a === 198 && b === 51 && c === 100 || a === 203 && b === 0 && c === 113);
469
+ }
470
+ /** `to_canonical()`: an IPv4-mapped address (`::ffff:a.b.c.d`) as its v4. */
471
+ function mappedV4(seg) {
472
+ if (seg.slice(0, 5).every((w) => w === 0) && seg[5] === 65535) return { v4: [
473
+ seg[6] >> 8,
474
+ seg[6] & 255,
475
+ seg[7] >> 8,
476
+ seg[7] & 255
477
+ ] };
478
+ return null;
479
+ }
480
+ /** `embedded_ipv4`: the v4 in a `::/96` or `64:ff9b::/96` address. */
481
+ function embeddedV4(seg) {
482
+ const compatible = seg.slice(0, 6).every((w) => w === 0);
483
+ const nat64 = seg[0] === 100 && seg[1] === 65435 && seg.slice(2, 6).every((w) => w === 0);
484
+ if (!compatible && !nat64) return null;
485
+ return [
486
+ seg[6] >> 8,
487
+ seg[6] & 255,
488
+ seg[7] >> 8,
489
+ seg[7] & 255
490
+ ];
491
+ }
492
+
493
+ //#endregion
494
+ //#region src/testing/host-error.ts
495
+ /** The `name` the runtime gives every refusal it unwraps. */
496
+ const HOST_ERROR_NAME = "HostError";
497
+ /**
498
+ * Render a refusal template: every `{placeholder}` replaced by `vars[name]`.
499
+ * A placeholder the caller did not supply is a bug in the context, not in the
500
+ * app under test, so it throws rather than leaking `{database}` into a message
501
+ * a test might then match on.
502
+ */
503
+ function render(template, vars = {}) {
504
+ return template.refusal.replace(/\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (whole, name) => {
505
+ const value = vars[name];
506
+ if (value === void 0) throw new Error(`test context bug: refusal template leaves {${name}} unfilled: ${whole}`);
507
+ return String(value);
508
+ });
509
+ }
510
+ /**
511
+ * The error a function sees when the host refuses: `name` `"HostError"`,
512
+ * message `"<surface>: <message>"`.
513
+ */
514
+ function hostError(surface, message) {
515
+ const err = /* @__PURE__ */ new Error(`${surface}: ${message}`);
516
+ err.name = HOST_ERROR_NAME;
517
+ return err;
518
+ }
519
+ /** `hostError` over a rendered template. */
520
+ function refuse(surface, template, vars = {}) {
521
+ return hostError(surface, render(template, vars));
522
+ }
523
+ /** Whether `err` is a refusal the context (or the runtime) threw. */
524
+ function isHostError(err) {
525
+ return err instanceof Error && err.name === "HostError";
526
+ }
527
+ /**
528
+ * An error in the context's OWN words — never the host's. Thrown where the
529
+ * context cannot model what the host would do (an unrecognised statement, an
530
+ * unregistered `fetch` answer) and says so, rather than answering something
531
+ * production would not. Its `name` is `"TestContextError"` so a test can never
532
+ * mistake it for a refusal.
533
+ */
534
+ function contextError(message) {
535
+ const err = /* @__PURE__ */ new Error(`@oxy-hq/sdk/testing: ${message}`);
536
+ err.name = "TestContextError";
537
+ return err;
538
+ }
539
+
540
+ //#endregion
541
+ //#region src/testing/gates.ts
542
+ const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
543
+ /** `spec.<a>.<b> === true` — `flag` in `capabilities.ts`. */
544
+ function flag(spec, a, b) {
545
+ const block = spec[a];
546
+ return isObject(block) && block[b] === true;
547
+ }
548
+ /**
549
+ * `MAX_NAME_LEN` in `crates/oltp/src/schema.rs`: 63 (Postgres) less `app_` and
550
+ * the longest role suffix `_rw`.
551
+ */
552
+ const MAX_SCHEMA_NAME_LEN = 56;
553
+ /**
554
+ * `app_writer_name` + `WriterRef::schema_name`: the schema an app's slug
555
+ * derives, or `null` when it derives none.
556
+ *
557
+ * Both halves matter. `app_writer_name` refuses a slug containing `_` outright
558
+ * — `my_app` would otherwise alias the hyphenated sibling `my-app` onto one
559
+ * schema and role — and then runs the derived name through `validate_name`,
560
+ * which is what rejects a leading digit, an over-long name, and any character
561
+ * outside `[a-z0-9_]`. Skipping that second half handed back a schema for slugs
562
+ * the host answers `None` for, which is the difference between a green test and
563
+ * a closed `ctx.oltp` in production.
564
+ */
565
+ function writerSchema(slug) {
566
+ if (slug.includes("_")) return null;
567
+ const name = slug.replace(/-/g, "_");
568
+ if (name === "" || name.length > 56) return null;
569
+ if (!/^[a-z]/.test(name)) return null;
570
+ if (!/^[a-z0-9_]+$/.test(name)) return null;
571
+ return `app_${name}`;
572
+ }
573
+ /** Read the gates for `functionName` from `manifest`, or throw naming what is missing. */
574
+ function readGates(manifest, functionName) {
575
+ const spec = manifest.functions?.[functionName];
576
+ if (!isObject(spec)) {
577
+ const known = Object.keys(manifest.functions ?? {});
578
+ throw contextError(`oxy-app.json declares no function "${functionName}" (functions: ${known.length ? known.join(", ") : "none"})`);
579
+ }
580
+ const slug = typeof manifest.slug === "string" ? manifest.slug : "";
581
+ const destinations = Array.isArray(spec.destinations) ? spec.destinations.filter((d) => typeof d === "string") : [];
582
+ const customerWarehouseWrites = {};
583
+ if (isObject(spec.customerWarehouseWrites)) {
584
+ for (const [db, reason] of Object.entries(spec.customerWarehouseWrites)) if (typeof reason === "string" && reason.trim() !== "") customerWarehouseWrites[db] = reason;
585
+ }
586
+ const fetch = isObject(spec.fetch) ? spec.fetch : {};
587
+ return {
588
+ functionName,
589
+ slug,
590
+ writerSchema: writerSchema(slug),
591
+ secretsWrite: flag(spec, "secrets", "write"),
592
+ emailSend: flag(spec, "email", "send"),
593
+ orgRead: flag(spec, "org", "read"),
594
+ storageRead: flag(spec, "storage", "read"),
595
+ storageWrite: flag(spec, "storage", "write"),
596
+ oltp: flag(spec, "oltp", "enabled"),
597
+ airhouse: flag(spec, "airhouse", "enabled"),
598
+ destinations,
599
+ customerWarehouseWrites,
600
+ fetchMaxBytes: typeof fetch.maxResponseBytes === "number" ? fetch.maxResponseBytes : null
601
+ };
602
+ }
603
+
604
+ //#endregion
605
+ //#region src/testing/run.ts
606
+ const B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
607
+ const B64R = (/* @__PURE__ */ new Uint8Array(256)).fill(255);
608
+ for (let i = 0; i < 64; i++) B64R[B64.charCodeAt(i)] = i;
609
+ /** `globalThis.btoa` as the isolate defines it: strings only, Latin1 only. */
610
+ function isolateBtoa(input) {
611
+ if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) throw new TypeError(render(REFUSALS.btoaBytes));
612
+ const s = String(input);
613
+ let out = "";
614
+ for (let i = 0; i < s.length; i += 3) {
615
+ const c0 = s.charCodeAt(i);
616
+ const c1 = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;
617
+ const c2 = i + 2 < s.length ? s.charCodeAt(i + 2) : 0;
618
+ if (c0 > 255 || c1 > 255 || c2 > 255) throw new TypeError("btoa: input contains characters outside the Latin1 range; for text pass it directly with { encoding: \"utf8\" }");
619
+ const n = c0 << 16 | c1 << 8 | c2;
620
+ out += B64[n >> 18 & 63] + B64[n >> 12 & 63] + (i + 1 < s.length ? B64[n >> 6 & 63] : "=") + (i + 2 < s.length ? B64[n & 63] : "=");
621
+ }
622
+ return out;
623
+ }
624
+ /** `globalThis.atob` as the isolate defines it: WHATWG forgiving-base64. */
625
+ function isolateAtob(input) {
626
+ let s = String(input).replace(/[ \t\n\f\r]/g, "");
627
+ if (s.length % 4 === 0) {
628
+ let pad = 0;
629
+ while (pad < 2 && s.charCodeAt(s.length - 1) === 61) {
630
+ s = s.slice(0, -1);
631
+ pad++;
632
+ }
633
+ }
634
+ if (s.indexOf("=") >= 0) throw new TypeError(render(REFUSALS.atobPadding));
635
+ if (s.length % 4 === 1) throw new TypeError(render(REFUSALS.atobLength));
636
+ let out = "";
637
+ let buf = 0;
638
+ let bits = 0;
639
+ for (let i = 0; i < s.length; i++) {
640
+ const code = s.charCodeAt(i);
641
+ const v = code < 256 ? B64R[code] : 255;
642
+ if (v === 255) throw new TypeError(`atob: invalid base64 character '${s[i]}'`);
643
+ buf = buf << 6 | v;
644
+ bits += 6;
645
+ if (bits >= 8) {
646
+ bits -= 8;
647
+ out += String.fromCharCode(buf >> bits & 255);
648
+ }
649
+ }
650
+ return out;
651
+ }
652
+ let running = false;
653
+ /**
654
+ * Evaluate `fn` with every `ABSENT_GLOBALS` entry removed from `globalThis` and
655
+ * `btoa` / `atob` replaced by the isolate's, restoring all of them afterwards
656
+ * — whether `fn` resolves or throws.
657
+ */
658
+ async function runWithoutIsolateGlobals(fn) {
659
+ if (running) throw contextError("t.run(fn) calls must not overlap — one at a time per test");
660
+ running = true;
661
+ const saved = [];
662
+ const g = globalThis;
663
+ const shadow = (name, value) => {
664
+ saved.push([name, Object.getOwnPropertyDescriptor(globalThis, name)]);
665
+ if (value === void 0) delete g[name];
666
+ else Object.defineProperty(globalThis, name, {
667
+ value,
668
+ configurable: true,
669
+ writable: true
670
+ });
671
+ };
672
+ try {
673
+ for (const entry of ABSENT_GLOBALS) shadow(entry.name, void 0);
674
+ shadow("btoa", isolateBtoa);
675
+ shadow("atob", isolateAtob);
676
+ return await fn();
677
+ } finally {
678
+ for (const [name, descriptor] of saved.reverse()) if (descriptor) Object.defineProperty(globalThis, name, descriptor);
679
+ else delete g[name];
680
+ running = false;
681
+ }
682
+ }
683
+
684
+ //#endregion
685
+ //#region src/testing/sql.ts
686
+ const STOP_WORDS = /^(DEFAULT|NOT|NULL|PRIMARY|UNIQUE|REFERENCES|CHECK|GENERATED|CODEC|COMMENT|TTL)$/i;
687
+ const CONSTRAINT_HEAD = /^(PRIMARY|UNIQUE|CONSTRAINT|FOREIGN|CHECK|KEY|INDEX)\b/i;
688
+ /** `sql` without its leading line and block comments and whitespace. */
689
+ function stripLeadingComments(sql) {
690
+ let s = sql;
691
+ for (;;) {
692
+ const before = s;
693
+ s = s.replace(/^\s+/, "").replace(/^--[^\n]*\n?/, "").replace(/^\/\*[\s\S]*?\*\//, "");
694
+ if (s === before) return s;
695
+ }
696
+ }
697
+ /** Parse one statement, or throw in the context's own words. */
698
+ function parse(sql) {
699
+ const text = stripLeadingComments(sql).replace(/;\s*$/, "");
700
+ switch (/^(\w+)/.exec(text)?.[1]?.toUpperCase() ?? "") {
701
+ case "CREATE": return parseCreate(text);
702
+ case "INSERT": return parseInsert(text);
703
+ case "SELECT":
704
+ case "WITH": return parseSelect(text);
705
+ case "DELETE": return parseDelete(text);
706
+ case "UPDATE": return parseUpdate(text);
707
+ default: throw unsupported(text);
708
+ }
709
+ }
710
+ function unsupported(sql) {
711
+ const head = sql.trim().slice(0, 60).replace(/\s+/g, " ");
712
+ return contextError(`the test context cannot evaluate this statement: "${head}…". It reads CREATE TABLE, INSERT … VALUES, SELECT <columns|count(*)|literals> FROM <table> [WHERE col = value AND …] [ORDER BY col] [LIMIT n], DELETE FROM and UPDATE … SET. Answer the call with t.override(op, …), or seed the rows it should find with t.state.<store>.raw(table, rows).`);
713
+ }
714
+ /** Strip the quotes an identifier was written with. */
715
+ function ident(raw) {
716
+ const s = raw.trim();
717
+ if (s.startsWith("\"") && s.endsWith("\"") || s.startsWith("`") && s.endsWith("`")) return s.slice(1, -1);
718
+ return s;
719
+ }
720
+ /** Split `text` on top-level commas, respecting parentheses, brackets and quotes. */
721
+ function splitTopLevel(text, separator = ",") {
722
+ const out = [];
723
+ let depth = 0;
724
+ let quote = null;
725
+ let start = 0;
726
+ for (let i = 0; i < text.length; i++) {
727
+ const c = text[i];
728
+ if (quote) {
729
+ if (c === quote) {
730
+ if (text[i + 1] === quote) i++;
731
+ else quote = null;
732
+ }
733
+ continue;
734
+ }
735
+ if (c === "'" || c === "\"" || c === "`") quote = c;
736
+ else if (c === "(" || c === "[") depth++;
737
+ else if (c === ")" || c === "]") depth--;
738
+ else if (depth === 0 && text.startsWith(separator, i)) {
739
+ out.push(text.slice(start, i).trim());
740
+ i += separator.length - 1;
741
+ start = i + 1;
742
+ }
743
+ }
744
+ out.push(text.slice(start).trim());
745
+ return out.filter((s) => s !== "");
746
+ }
747
+ /** The index just past the `)` matching the `(` at `open`. */
748
+ function closeParen(text, open) {
749
+ let depth = 0;
750
+ let quote = null;
751
+ for (let i = open; i < text.length; i++) {
752
+ const c = text[i];
753
+ if (quote) {
754
+ if (c === quote) {
755
+ if (text[i + 1] === quote) i++;
756
+ else quote = null;
757
+ }
758
+ continue;
759
+ }
760
+ if (c === "'" || c === "\"") quote = c;
761
+ else if (c === "(") depth++;
762
+ else if (c === ")" && --depth === 0) return i + 1;
763
+ }
764
+ throw unsupported(text);
765
+ }
766
+ function parseCreate(text) {
767
+ const m = /^CREATE\s+TABLE\s+(IF\s+NOT\s+EXISTS\s+)?([\w."`]+)\s*\(/i.exec(text);
768
+ if (!m) throw unsupported(text);
769
+ const open = m[0].length - 1;
770
+ const end = closeParen(text, open);
771
+ const columns = [];
772
+ for (const def of splitTopLevel(text.slice(open + 1, end - 1))) {
773
+ if (CONSTRAINT_HEAD.test(def)) continue;
774
+ const words = splitTopLevel(def, " ");
775
+ const name = ident(words[0] ?? "");
776
+ const typeWords = splitTopLevel(def.slice(def.indexOf(words[0] ?? "") + (words[0]?.length ?? 0)).trim(), " ");
777
+ const stop = typeWords.findIndex((w) => STOP_WORDS.test(w));
778
+ const type = (stop < 0 ? typeWords : typeWords.slice(0, stop)).join(" ");
779
+ if (name) columns.push({
780
+ name,
781
+ type
782
+ });
783
+ }
784
+ return {
785
+ kind: "create",
786
+ table: ident(m[2]),
787
+ ifNotExists: Boolean(m[1]),
788
+ columns
789
+ };
790
+ }
791
+ function parseInsert(text) {
792
+ const m = /^INSERT\s+INTO\s+([\w."`]+)\s*(\(([^)]*)\))?\s*VALUES\s*/i.exec(text);
793
+ if (!m) throw unsupported(text);
794
+ const columns = m[3] ? splitTopLevel(m[3]).map(ident) : null;
795
+ const tuples = [];
796
+ let at = m[0].length;
797
+ while (at < text.length) {
798
+ if (text[at] !== "(") throw unsupported(text);
799
+ const end = closeParen(text, at);
800
+ tuples.push(splitTopLevel(text.slice(at + 1, end - 1)));
801
+ at = end;
802
+ const gap = /^\s*,?\s*/.exec(text.slice(at))?.[0] ?? "";
803
+ at += gap.length;
804
+ }
805
+ return {
806
+ kind: "insert",
807
+ table: ident(m[1]),
808
+ columns,
809
+ tuples
810
+ };
811
+ }
812
+ /** `a = 1 AND b = 'x' AND c IN (1, 2)` → predicates; anything else throws. */
813
+ function parseWhere(text, whole) {
814
+ if (!text) return [];
815
+ return splitTopLevel(text, " AND ").map((clause) => {
816
+ const eq = /^([\w."`]+)\s*=\s*(.+)$/s.exec(clause);
817
+ if (eq) return {
818
+ column: ident(eq[1]),
819
+ values: [eq[2].trim()]
820
+ };
821
+ const inList = /^([\w."`]+)\s+IN\s*\((.*)\)$/is.exec(clause);
822
+ if (inList) return {
823
+ column: ident(inList[1]),
824
+ values: splitTopLevel(inList[2])
825
+ };
826
+ throw contextError(`the test context cannot evaluate this WHERE clause: "${clause}". It reads "col = value" and "col IN (…)" joined by AND. Answer the call with t.override(op, …) instead: ${whole.slice(0, 80)}`);
827
+ });
828
+ }
829
+ /**
830
+ * Whether `literal()` will read this expression as a value rather than hand it
831
+ * back as its own SQL text. The two must agree: a projection the parser accepts
832
+ * as a literal but `literal()` cannot read comes back to the caller as the SQL
833
+ * they wrote — a column named `sum(amount)` holding the string `"sum(amount)"`,
834
+ * which is the one thing this module promises never to do.
835
+ */
836
+ function isReadableLiteral(expr) {
837
+ const s = expr.trim();
838
+ return /^\$\d+$/.test(s) || /^(NULL|TRUE|FALSE)$/i.test(s) || s.startsWith("'") && s.endsWith("'") && s.length >= 2 || /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(s);
839
+ }
840
+ /**
841
+ * The statement with every quoted string blanked, so a keyword scan reads the
842
+ * SQL and not the data: `WHERE label = 'GROUP BY'` is a row, not a grouping.
843
+ */
844
+ function withoutStringLiterals(text) {
845
+ return text.replace(/'(?:[^']|'')*'/g, "''");
846
+ }
847
+ function parseSelect(text) {
848
+ if (/\bGROUP\s+BY\b/is.test(withoutStringLiterals(text))) throw contextError(`the test context cannot evaluate GROUP BY: "${text.trim().slice(0, 60).replace(/\s+/g, " ")}…". It would have to aggregate, and a wrong aggregate reads like a right one. Answer the call with t.override(op, …) and assert on the arguments instead.`);
849
+ const m = /^SELECT\s+(.*?)(?:\s+FROM\s+([\w."`]+))?(?:\s+WHERE\s+(.*?))?(?:\s+ORDER\s+BY\s+([\w."`]+)(?:\s+(ASC|DESC))?)?(?:\s+LIMIT\s+(\d+))?\s*$/is.exec(text);
850
+ if (!m || !m[2] && /\bFROM\b/i.test(m[1])) throw unsupported(text);
851
+ const items = splitTopLevel(m[1]).map((item) => {
852
+ if (item === "*") return { kind: "all" };
853
+ const aliased = /^(.*?)\s+AS\s+([\w"`]+)$/is.exec(item);
854
+ const expr = (aliased ? aliased[1] : item).trim();
855
+ const alias = aliased ? ident(aliased[2]) : null;
856
+ if (/^count\s*\(\s*\*\s*\)$/i.test(expr)) return {
857
+ kind: "count",
858
+ alias: alias ?? "count(*)"
859
+ };
860
+ if (/^[\w."`]+$/.test(expr) && !/^\d/.test(expr) && !/^(true|false|null)$/i.test(expr)) return {
861
+ kind: "column",
862
+ column: ident(expr),
863
+ alias: alias ?? ident(expr)
864
+ };
865
+ if (!isReadableLiteral(expr)) throw unsupported(text);
866
+ return {
867
+ kind: "literal",
868
+ raw: expr,
869
+ alias: alias ?? expr
870
+ };
871
+ });
872
+ return {
873
+ kind: "select",
874
+ table: m[2] ? ident(m[2]) : null,
875
+ items,
876
+ where: parseWhere(m[3], text),
877
+ orderBy: m[4] ? {
878
+ column: ident(m[4]),
879
+ desc: (m[5] ?? "").toUpperCase() === "DESC"
880
+ } : null,
881
+ limit: m[6] ? Number(m[6]) : null
882
+ };
883
+ }
884
+ function parseDelete(text) {
885
+ const m = /^DELETE\s+FROM\s+([\w."`]+)(?:\s+WHERE\s+(.*))?\s*$/is.exec(text);
886
+ if (!m) throw unsupported(text);
887
+ return {
888
+ kind: "delete",
889
+ table: ident(m[1]),
890
+ where: parseWhere(m[2], text)
891
+ };
892
+ }
893
+ function parseUpdate(text) {
894
+ const m = /^UPDATE\s+([\w."`]+)\s+SET\s+(.*?)(?:\s+WHERE\s+(.*))?\s*$/is.exec(text);
895
+ if (!m) throw unsupported(text);
896
+ const set = splitTopLevel(m[2]).map((assignment) => {
897
+ const eq = /^([\w."`]+)\s*=\s*(.+)$/s.exec(assignment);
898
+ if (!eq) throw unsupported(text);
899
+ const raw = eq[2].trim();
900
+ if (!isReadableLiteral(raw)) throw unsupported(text);
901
+ return {
902
+ column: ident(eq[1]),
903
+ raw
904
+ };
905
+ });
906
+ return {
907
+ kind: "update",
908
+ table: ident(m[1]),
909
+ set,
910
+ where: parseWhere(m[3], text)
911
+ };
912
+ }
913
+ /**
914
+ * A raw SQL value as a JS value, with no engine's rendering applied: a quoted
915
+ * string, a number, NULL, TRUE/FALSE, or a `$n` bound parameter. Anything else
916
+ * (a function call, a cast, an array literal) stays as its SQL text.
917
+ */
918
+ function literal(raw, params = []) {
919
+ const s = raw.trim();
920
+ const param = /^\$(\d+)$/.exec(s);
921
+ if (param) return params[Number(param[1]) - 1];
922
+ if (/^NULL$/i.test(s)) return null;
923
+ if (/^TRUE$/i.test(s)) return true;
924
+ if (/^FALSE$/i.test(s)) return false;
925
+ if (s.startsWith("'") && s.endsWith("'")) return s.slice(1, -1).replace(/''/g, "'");
926
+ if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(s)) return Number(s);
927
+ return s;
928
+ }
929
+
930
+ //#endregion
931
+ //#region src/testing/shape-zoo.json
932
+ var shape_zoo_default = {
933
+ version: 1,
934
+ engines: {
935
+ "clickhouse": { "cases": [
936
+ {
937
+ "key": "clickhouse/Bool/plain",
938
+ "native_type": "Bool",
939
+ "class": "plain",
940
+ "value_sql": "true",
941
+ "expect": { "warehouse": true }
942
+ },
943
+ {
944
+ "key": "clickhouse/Nullable(Bool)/null",
945
+ "native_type": "Nullable(Bool)",
946
+ "class": "null",
947
+ "value_sql": "NULL",
948
+ "expect": { "warehouse": null }
949
+ },
950
+ {
951
+ "key": "clickhouse/Boolean/plain",
952
+ "native_type": "Boolean",
953
+ "class": "plain",
954
+ "value_sql": "false",
955
+ "expect": { "warehouse": false }
956
+ },
957
+ {
958
+ "key": "clickhouse/Int8/plain",
959
+ "native_type": "Int8",
960
+ "class": "plain",
961
+ "value_sql": "42",
962
+ "expect": { "warehouse": 42 }
963
+ },
964
+ {
965
+ "key": "clickhouse/Int8/negative",
966
+ "native_type": "Int8",
967
+ "class": "negative",
968
+ "value_sql": "-128",
969
+ "expect": { "warehouse": -128 }
970
+ },
971
+ {
972
+ "key": "clickhouse/Int8/zero",
973
+ "native_type": "Int8",
974
+ "class": "zero",
975
+ "value_sql": "0",
976
+ "expect": { "warehouse": 0 }
977
+ },
978
+ {
979
+ "key": "clickhouse/Nullable(Int8)/null",
980
+ "native_type": "Nullable(Int8)",
981
+ "class": "null",
982
+ "value_sql": "NULL",
983
+ "expect": { "warehouse": null }
984
+ },
985
+ {
986
+ "key": "clickhouse/Int16/plain",
987
+ "native_type": "Int16",
988
+ "class": "plain",
989
+ "value_sql": "42",
990
+ "expect": { "warehouse": 42 }
991
+ },
992
+ {
993
+ "key": "clickhouse/Int16/negative",
994
+ "native_type": "Int16",
995
+ "class": "negative",
996
+ "value_sql": "-32768",
997
+ "expect": { "warehouse": -32768 }
998
+ },
999
+ {
1000
+ "key": "clickhouse/Int16/zero",
1001
+ "native_type": "Int16",
1002
+ "class": "zero",
1003
+ "value_sql": "0",
1004
+ "expect": { "warehouse": 0 }
1005
+ },
1006
+ {
1007
+ "key": "clickhouse/Nullable(Int16)/null",
1008
+ "native_type": "Nullable(Int16)",
1009
+ "class": "null",
1010
+ "value_sql": "NULL",
1011
+ "expect": { "warehouse": null }
1012
+ },
1013
+ {
1014
+ "key": "clickhouse/Int32/plain",
1015
+ "native_type": "Int32",
1016
+ "class": "plain",
1017
+ "value_sql": "42",
1018
+ "expect": { "warehouse": 42 }
1019
+ },
1020
+ {
1021
+ "key": "clickhouse/Int32/negative",
1022
+ "native_type": "Int32",
1023
+ "class": "negative",
1024
+ "value_sql": "-2147483648",
1025
+ "expect": { "warehouse": -2147483648 }
1026
+ },
1027
+ {
1028
+ "key": "clickhouse/Int32/zero",
1029
+ "native_type": "Int32",
1030
+ "class": "zero",
1031
+ "value_sql": "0",
1032
+ "expect": { "warehouse": 0 }
1033
+ },
1034
+ {
1035
+ "key": "clickhouse/Nullable(Int32)/null",
1036
+ "native_type": "Nullable(Int32)",
1037
+ "class": "null",
1038
+ "value_sql": "NULL",
1039
+ "expect": { "warehouse": null }
1040
+ },
1041
+ {
1042
+ "key": "clickhouse/Int64/plain",
1043
+ "native_type": "Int64",
1044
+ "class": "plain",
1045
+ "value_sql": "42",
1046
+ "expect": { "warehouse": 42 }
1047
+ },
1048
+ {
1049
+ "key": "clickhouse/Int64/negative",
1050
+ "native_type": "Int64",
1051
+ "class": "negative",
1052
+ "value_sql": "-9007199254740991",
1053
+ "expect": { "warehouse": -9007199254740991 }
1054
+ },
1055
+ {
1056
+ "key": "clickhouse/Int64/zero",
1057
+ "native_type": "Int64",
1058
+ "class": "zero",
1059
+ "value_sql": "0",
1060
+ "expect": { "warehouse": 0 }
1061
+ },
1062
+ {
1063
+ "key": "clickhouse/Int64/precision_gt_18",
1064
+ "native_type": "Int64",
1065
+ "class": "precision_gt_18",
1066
+ "value_sql": "9223372036854775807",
1067
+ "expect": { "warehouse": 0x8000000000000000 }
1068
+ },
1069
+ {
1070
+ "key": "clickhouse/Nullable(Int64)/null",
1071
+ "native_type": "Nullable(Int64)",
1072
+ "class": "null",
1073
+ "value_sql": "NULL",
1074
+ "expect": { "warehouse": null }
1075
+ },
1076
+ {
1077
+ "key": "clickhouse/UInt8/plain",
1078
+ "native_type": "UInt8",
1079
+ "class": "plain",
1080
+ "value_sql": "42",
1081
+ "expect": { "warehouse": 42 }
1082
+ },
1083
+ {
1084
+ "key": "clickhouse/UInt8/zero",
1085
+ "native_type": "UInt8",
1086
+ "class": "zero",
1087
+ "value_sql": "0",
1088
+ "expect": { "warehouse": 0 }
1089
+ },
1090
+ {
1091
+ "key": "clickhouse/Nullable(UInt8)/null",
1092
+ "native_type": "Nullable(UInt8)",
1093
+ "class": "null",
1094
+ "value_sql": "NULL",
1095
+ "expect": { "warehouse": null }
1096
+ },
1097
+ {
1098
+ "key": "clickhouse/UInt16/plain",
1099
+ "native_type": "UInt16",
1100
+ "class": "plain",
1101
+ "value_sql": "42",
1102
+ "expect": { "warehouse": 42 }
1103
+ },
1104
+ {
1105
+ "key": "clickhouse/UInt16/zero",
1106
+ "native_type": "UInt16",
1107
+ "class": "zero",
1108
+ "value_sql": "0",
1109
+ "expect": { "warehouse": 0 }
1110
+ },
1111
+ {
1112
+ "key": "clickhouse/Nullable(UInt16)/null",
1113
+ "native_type": "Nullable(UInt16)",
1114
+ "class": "null",
1115
+ "value_sql": "NULL",
1116
+ "expect": { "warehouse": null }
1117
+ },
1118
+ {
1119
+ "key": "clickhouse/UInt32/plain",
1120
+ "native_type": "UInt32",
1121
+ "class": "plain",
1122
+ "value_sql": "42",
1123
+ "expect": { "warehouse": 42 }
1124
+ },
1125
+ {
1126
+ "key": "clickhouse/UInt32/zero",
1127
+ "native_type": "UInt32",
1128
+ "class": "zero",
1129
+ "value_sql": "0",
1130
+ "expect": { "warehouse": 0 }
1131
+ },
1132
+ {
1133
+ "key": "clickhouse/Nullable(UInt32)/null",
1134
+ "native_type": "Nullable(UInt32)",
1135
+ "class": "null",
1136
+ "value_sql": "NULL",
1137
+ "expect": { "warehouse": null }
1138
+ },
1139
+ {
1140
+ "key": "clickhouse/UInt64/plain",
1141
+ "native_type": "UInt64",
1142
+ "class": "plain",
1143
+ "value_sql": "42",
1144
+ "expect": { "warehouse": 42 }
1145
+ },
1146
+ {
1147
+ "key": "clickhouse/UInt64/zero",
1148
+ "native_type": "UInt64",
1149
+ "class": "zero",
1150
+ "value_sql": "0",
1151
+ "expect": { "warehouse": 0 }
1152
+ },
1153
+ {
1154
+ "key": "clickhouse/UInt64/precision_gt_18",
1155
+ "native_type": "UInt64",
1156
+ "class": "precision_gt_18",
1157
+ "value_sql": "18446744073709551615",
1158
+ "expect": { "warehouse": "18446744073709551615" }
1159
+ },
1160
+ {
1161
+ "key": "clickhouse/Nullable(UInt64)/null",
1162
+ "native_type": "Nullable(UInt64)",
1163
+ "class": "null",
1164
+ "value_sql": "NULL",
1165
+ "expect": { "warehouse": null }
1166
+ },
1167
+ {
1168
+ "key": "clickhouse/Int128/plain",
1169
+ "native_type": "Int128",
1170
+ "class": "plain",
1171
+ "value_sql": "42",
1172
+ "expect": { "warehouse": "42" }
1173
+ },
1174
+ {
1175
+ "key": "clickhouse/Int128/negative",
1176
+ "native_type": "Int128",
1177
+ "class": "negative",
1178
+ "value_sql": "-42",
1179
+ "expect": { "warehouse": "-42" }
1180
+ },
1181
+ {
1182
+ "key": "clickhouse/Int128/zero",
1183
+ "native_type": "Int128",
1184
+ "class": "zero",
1185
+ "value_sql": "0",
1186
+ "expect": { "warehouse": "0" }
1187
+ },
1188
+ {
1189
+ "key": "clickhouse/Int128/precision_gt_18",
1190
+ "native_type": "Int128",
1191
+ "class": "precision_gt_18",
1192
+ "value_sql": "toInt128('-170141183460469231731687303715884105728')",
1193
+ "expect": { "warehouse": "-170141183460469231731687303715884105728" }
1194
+ },
1195
+ {
1196
+ "key": "clickhouse/Nullable(Int128)/null",
1197
+ "native_type": "Nullable(Int128)",
1198
+ "class": "null",
1199
+ "value_sql": "NULL",
1200
+ "expect": { "warehouse": null }
1201
+ },
1202
+ {
1203
+ "key": "clickhouse/UInt128/plain",
1204
+ "native_type": "UInt128",
1205
+ "class": "plain",
1206
+ "value_sql": "42",
1207
+ "expect": { "warehouse": "42" }
1208
+ },
1209
+ {
1210
+ "key": "clickhouse/UInt128/zero",
1211
+ "native_type": "UInt128",
1212
+ "class": "zero",
1213
+ "value_sql": "0",
1214
+ "expect": { "warehouse": "0" }
1215
+ },
1216
+ {
1217
+ "key": "clickhouse/UInt128/precision_gt_18",
1218
+ "native_type": "UInt128",
1219
+ "class": "precision_gt_18",
1220
+ "value_sql": "toUInt128('340282366920938463463374607431768211455')",
1221
+ "expect": { "warehouse": "340282366920938463463374607431768211455" }
1222
+ },
1223
+ {
1224
+ "key": "clickhouse/Nullable(UInt128)/null",
1225
+ "native_type": "Nullable(UInt128)",
1226
+ "class": "null",
1227
+ "value_sql": "NULL",
1228
+ "expect": { "warehouse": null }
1229
+ },
1230
+ {
1231
+ "key": "clickhouse/Int256/plain",
1232
+ "native_type": "Int256",
1233
+ "class": "plain",
1234
+ "value_sql": "42",
1235
+ "expect": { "warehouse": "42" }
1236
+ },
1237
+ {
1238
+ "key": "clickhouse/Int256/negative",
1239
+ "native_type": "Int256",
1240
+ "class": "negative",
1241
+ "value_sql": "-42",
1242
+ "expect": { "warehouse": "-42" }
1243
+ },
1244
+ {
1245
+ "key": "clickhouse/Int256/zero",
1246
+ "native_type": "Int256",
1247
+ "class": "zero",
1248
+ "value_sql": "0",
1249
+ "expect": { "warehouse": "0" }
1250
+ },
1251
+ {
1252
+ "key": "clickhouse/Int256/precision_gt_18",
1253
+ "native_type": "Int256",
1254
+ "class": "precision_gt_18",
1255
+ "value_sql": "toInt256('-57896044618658097711785492504343953926634992332820282019728792003956564819968')",
1256
+ "expect": { "warehouse": "-57896044618658097711785492504343953926634992332820282019728792003956564819968" }
1257
+ },
1258
+ {
1259
+ "key": "clickhouse/Nullable(Int256)/null",
1260
+ "native_type": "Nullable(Int256)",
1261
+ "class": "null",
1262
+ "value_sql": "NULL",
1263
+ "expect": { "warehouse": null }
1264
+ },
1265
+ {
1266
+ "key": "clickhouse/UInt256/plain",
1267
+ "native_type": "UInt256",
1268
+ "class": "plain",
1269
+ "value_sql": "42",
1270
+ "expect": { "warehouse": "42" }
1271
+ },
1272
+ {
1273
+ "key": "clickhouse/UInt256/zero",
1274
+ "native_type": "UInt256",
1275
+ "class": "zero",
1276
+ "value_sql": "0",
1277
+ "expect": { "warehouse": "0" }
1278
+ },
1279
+ {
1280
+ "key": "clickhouse/UInt256/precision_gt_18",
1281
+ "native_type": "UInt256",
1282
+ "class": "precision_gt_18",
1283
+ "value_sql": "toUInt256('115792089237316195423570985008687907853269984665640564039457584007913129639935')",
1284
+ "expect": { "warehouse": "115792089237316195423570985008687907853269984665640564039457584007913129639935" }
1285
+ },
1286
+ {
1287
+ "key": "clickhouse/Nullable(UInt256)/null",
1288
+ "native_type": "Nullable(UInt256)",
1289
+ "class": "null",
1290
+ "value_sql": "NULL",
1291
+ "expect": { "warehouse": null }
1292
+ },
1293
+ {
1294
+ "key": "clickhouse/Float32/plain",
1295
+ "native_type": "Float32",
1296
+ "class": "plain",
1297
+ "value_sql": "0.1",
1298
+ "expect": { "warehouse": .1 }
1299
+ },
1300
+ {
1301
+ "key": "clickhouse/Float32/negative",
1302
+ "native_type": "Float32",
1303
+ "class": "negative",
1304
+ "value_sql": "-1.5",
1305
+ "expect": { "warehouse": -1.5 }
1306
+ },
1307
+ {
1308
+ "key": "clickhouse/Float32/zero",
1309
+ "native_type": "Float32",
1310
+ "class": "zero",
1311
+ "value_sql": "0",
1312
+ "expect": { "warehouse": 0 }
1313
+ },
1314
+ {
1315
+ "key": "clickhouse/Float32/nan_inf",
1316
+ "native_type": "Float32",
1317
+ "class": "nan_inf",
1318
+ "value_sql": "nan",
1319
+ "expect": { "warehouse": null }
1320
+ },
1321
+ {
1322
+ "key": "clickhouse/Nullable(Float32)/null",
1323
+ "native_type": "Nullable(Float32)",
1324
+ "class": "null",
1325
+ "value_sql": "NULL",
1326
+ "expect": { "warehouse": null }
1327
+ },
1328
+ {
1329
+ "key": "clickhouse/Float64/plain",
1330
+ "native_type": "Float64",
1331
+ "class": "plain",
1332
+ "value_sql": "0.1",
1333
+ "expect": { "warehouse": .1 }
1334
+ },
1335
+ {
1336
+ "key": "clickhouse/Float64/negative",
1337
+ "native_type": "Float64",
1338
+ "class": "negative",
1339
+ "value_sql": "-1.5",
1340
+ "expect": { "warehouse": -1.5 }
1341
+ },
1342
+ {
1343
+ "key": "clickhouse/Float64/zero",
1344
+ "native_type": "Float64",
1345
+ "class": "zero",
1346
+ "value_sql": "0",
1347
+ "expect": { "warehouse": 0 }
1348
+ },
1349
+ {
1350
+ "key": "clickhouse/Float64/nan_inf",
1351
+ "native_type": "Float64",
1352
+ "class": "nan_inf",
1353
+ "value_sql": "inf",
1354
+ "expect": { "warehouse": null }
1355
+ },
1356
+ {
1357
+ "key": "clickhouse/Nullable(Float64)/null",
1358
+ "native_type": "Nullable(Float64)",
1359
+ "class": "null",
1360
+ "value_sql": "NULL",
1361
+ "expect": { "warehouse": null }
1362
+ },
1363
+ {
1364
+ "key": "clickhouse/Decimal(18, 4)/plain",
1365
+ "native_type": "Decimal(18, 4)",
1366
+ "class": "plain",
1367
+ "value_sql": "1234.5678",
1368
+ "expect": { "warehouse": "1234.5678" }
1369
+ },
1370
+ {
1371
+ "key": "clickhouse/Decimal(18, 4)/negative",
1372
+ "native_type": "Decimal(18, 4)",
1373
+ "class": "negative",
1374
+ "value_sql": "-1.25",
1375
+ "expect": { "warehouse": "-1.25" }
1376
+ },
1377
+ {
1378
+ "key": "clickhouse/Decimal(18, 4)/zero",
1379
+ "native_type": "Decimal(18, 4)",
1380
+ "class": "zero",
1381
+ "value_sql": "0",
1382
+ "expect": { "warehouse": "0" }
1383
+ },
1384
+ {
1385
+ "key": "clickhouse/Nullable(Decimal(18, 4))/null",
1386
+ "native_type": "Nullable(Decimal(18, 4))",
1387
+ "class": "null",
1388
+ "value_sql": "NULL",
1389
+ "expect": { "warehouse": null }
1390
+ },
1391
+ {
1392
+ "key": "clickhouse/Decimal(38, 10)/precision_gt_18",
1393
+ "native_type": "Decimal(38, 10)",
1394
+ "class": "precision_gt_18",
1395
+ "value_sql": "toDecimal128('1234567890123456789.0123456789', 10)",
1396
+ "expect": { "warehouse": "1.2345678901234568e+18" }
1397
+ },
1398
+ {
1399
+ "key": "clickhouse/Decimal(38, 0)/precision_gt_18",
1400
+ "native_type": "Decimal(38, 0)",
1401
+ "class": "precision_gt_18",
1402
+ "value_sql": "toDecimal128('12345678901234567890123456789012345678', 0)",
1403
+ "expect": { "warehouse": "12345678901234567890123456789012345678" }
1404
+ },
1405
+ {
1406
+ "key": "clickhouse/Decimal32(4)/plain",
1407
+ "native_type": "Decimal32(4)",
1408
+ "class": "plain",
1409
+ "value_sql": "1.5",
1410
+ "expect": { "warehouse": "1.5" }
1411
+ },
1412
+ {
1413
+ "key": "clickhouse/Date/plain",
1414
+ "native_type": "Date",
1415
+ "class": "plain",
1416
+ "value_sql": "'2024-03-10'",
1417
+ "expect": { "warehouse": "2024-03-10" }
1418
+ },
1419
+ {
1420
+ "key": "clickhouse/Date/date_before_1970",
1421
+ "native_type": "Date",
1422
+ "class": "date_before_1970",
1423
+ "value_sql": "'1969-12-31'",
1424
+ "expect": { "warehouse": "1970-01-01" }
1425
+ },
1426
+ {
1427
+ "key": "clickhouse/Date/date_after_2100",
1428
+ "native_type": "Date",
1429
+ "class": "date_after_2100",
1430
+ "value_sql": "'2149-06-06'",
1431
+ "expect": { "warehouse": "2149-06-06" }
1432
+ },
1433
+ {
1434
+ "key": "clickhouse/Nullable(Date)/null",
1435
+ "native_type": "Nullable(Date)",
1436
+ "class": "null",
1437
+ "value_sql": "NULL",
1438
+ "expect": { "warehouse": null }
1439
+ },
1440
+ {
1441
+ "key": "clickhouse/Date32/plain",
1442
+ "native_type": "Date32",
1443
+ "class": "plain",
1444
+ "value_sql": "'2024-03-10'",
1445
+ "expect": { "warehouse": "2024-03-10" }
1446
+ },
1447
+ {
1448
+ "key": "clickhouse/Date32/date_before_1970",
1449
+ "native_type": "Date32",
1450
+ "class": "date_before_1970",
1451
+ "value_sql": "'1900-01-01'",
1452
+ "expect": { "warehouse": "1900-01-01" }
1453
+ },
1454
+ {
1455
+ "key": "clickhouse/Date32/date_after_2100",
1456
+ "native_type": "Date32",
1457
+ "class": "date_after_2100",
1458
+ "value_sql": "'2299-12-31'",
1459
+ "expect": { "warehouse": "2299-12-31" }
1460
+ },
1461
+ {
1462
+ "key": "clickhouse/Nullable(Date32)/null",
1463
+ "native_type": "Nullable(Date32)",
1464
+ "class": "null",
1465
+ "value_sql": "NULL",
1466
+ "expect": { "warehouse": null }
1467
+ },
1468
+ {
1469
+ "key": "clickhouse/DateTime/plain",
1470
+ "native_type": "DateTime",
1471
+ "class": "plain",
1472
+ "value_sql": "'2024-03-10 12:34:56'",
1473
+ "expect": { "warehouse": "2024-03-10 12:34:56" }
1474
+ },
1475
+ {
1476
+ "key": "clickhouse/DateTime/date_before_1970",
1477
+ "native_type": "DateTime",
1478
+ "class": "date_before_1970",
1479
+ "value_sql": "'1969-12-31 23:59:59'",
1480
+ "expect": { "warehouse": "1970-01-01 00:00:00" }
1481
+ },
1482
+ {
1483
+ "key": "clickhouse/DateTime/date_after_2100",
1484
+ "native_type": "DateTime",
1485
+ "class": "date_after_2100",
1486
+ "value_sql": "'2105-12-31 23:59:59'",
1487
+ "expect": { "warehouse": "2105-12-31 23:59:59" }
1488
+ },
1489
+ {
1490
+ "key": "clickhouse/Nullable(DateTime)/null",
1491
+ "native_type": "Nullable(DateTime)",
1492
+ "class": "null",
1493
+ "value_sql": "NULL",
1494
+ "expect": { "warehouse": null }
1495
+ },
1496
+ {
1497
+ "key": "clickhouse/DateTime('Asia/Kolkata')/tz_bearing",
1498
+ "native_type": "DateTime('Asia/Kolkata')",
1499
+ "class": "tz_bearing",
1500
+ "value_sql": "'2024-03-10 12:34:56'",
1501
+ "expect": { "warehouse": "2024-03-10 12:34:56" }
1502
+ },
1503
+ {
1504
+ "key": "clickhouse/DateTime64(3)/plain",
1505
+ "native_type": "DateTime64(3)",
1506
+ "class": "plain",
1507
+ "value_sql": "'2024-03-10 12:34:56.789'",
1508
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
1509
+ },
1510
+ {
1511
+ "key": "clickhouse/DateTime64(3)/date_before_1970",
1512
+ "native_type": "DateTime64(3)",
1513
+ "class": "date_before_1970",
1514
+ "value_sql": "'1969-07-20 20:17:40.500'",
1515
+ "expect": { "warehouse": "1969-07-20 20:17:40.500000" }
1516
+ },
1517
+ {
1518
+ "key": "clickhouse/DateTime64(3)/date_after_2100",
1519
+ "native_type": "DateTime64(3)",
1520
+ "class": "date_after_2100",
1521
+ "value_sql": "'2150-01-01 00:00:00.000'",
1522
+ "expect": { "warehouse": "2150-01-01 00:00:00" }
1523
+ },
1524
+ {
1525
+ "key": "clickhouse/Nullable(DateTime64(3))/null",
1526
+ "native_type": "Nullable(DateTime64(3))",
1527
+ "class": "null",
1528
+ "value_sql": "NULL",
1529
+ "expect": { "warehouse": null }
1530
+ },
1531
+ {
1532
+ "key": "clickhouse/DateTime64(6, 'America/New_York')/tz_bearing",
1533
+ "native_type": "DateTime64(6, 'America/New_York')",
1534
+ "class": "tz_bearing",
1535
+ "value_sql": "'2024-03-10 12:34:56.123456'",
1536
+ "expect": { "warehouse": "2024-03-10 12:34:56.123456" }
1537
+ },
1538
+ {
1539
+ "key": "clickhouse/String/plain",
1540
+ "native_type": "String",
1541
+ "class": "plain",
1542
+ "value_sql": "'plain text'",
1543
+ "expect": { "warehouse": "plain text" }
1544
+ },
1545
+ {
1546
+ "key": "clickhouse/String/empty",
1547
+ "native_type": "String",
1548
+ "class": "empty",
1549
+ "value_sql": "''",
1550
+ "expect": { "warehouse": "" }
1551
+ },
1552
+ {
1553
+ "key": "clickhouse/String/whitespace",
1554
+ "native_type": "String",
1555
+ "class": "whitespace",
1556
+ "value_sql": "' \\t\\n '",
1557
+ "expect": { "warehouse": " \n " }
1558
+ },
1559
+ {
1560
+ "key": "clickhouse/String/non_bmp",
1561
+ "native_type": "String",
1562
+ "class": "non_bmp",
1563
+ "value_sql": "'𝔘nicode'",
1564
+ "expect": { "warehouse": "𝔘nicode" }
1565
+ },
1566
+ {
1567
+ "key": "clickhouse/String/len_gt_1k",
1568
+ "native_type": "String",
1569
+ "class": "len_gt_1k",
1570
+ "value_sql": "repeat('0123456789', 101)",
1571
+ "expect": { "warehouse": "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" }
1572
+ },
1573
+ {
1574
+ "key": "clickhouse/Nullable(String)/null",
1575
+ "native_type": "Nullable(String)",
1576
+ "class": "null",
1577
+ "value_sql": "NULL",
1578
+ "expect": { "warehouse": null }
1579
+ },
1580
+ {
1581
+ "key": "clickhouse/FixedString(4)/plain",
1582
+ "native_type": "FixedString(4)",
1583
+ "class": "plain",
1584
+ "value_sql": "'ab'",
1585
+ "expect": { "warehouse": "ab\0\0" }
1586
+ },
1587
+ {
1588
+ "key": "clickhouse/FixedString(4)/empty",
1589
+ "native_type": "FixedString(4)",
1590
+ "class": "empty",
1591
+ "value_sql": "''",
1592
+ "expect": { "warehouse": "\0\0\0\0" }
1593
+ },
1594
+ {
1595
+ "key": "clickhouse/Nullable(FixedString(4))/null",
1596
+ "native_type": "Nullable(FixedString(4))",
1597
+ "class": "null",
1598
+ "value_sql": "NULL",
1599
+ "expect": { "warehouse": null }
1600
+ },
1601
+ {
1602
+ "key": "clickhouse/LowCardinality(String)/plain",
1603
+ "native_type": "LowCardinality(String)",
1604
+ "class": "plain",
1605
+ "value_sql": "'low cardinality'",
1606
+ "expect": { "warehouse": "low cardinality" }
1607
+ },
1608
+ {
1609
+ "key": "clickhouse/LowCardinality(Nullable(String))/null",
1610
+ "native_type": "LowCardinality(Nullable(String))",
1611
+ "class": "null",
1612
+ "value_sql": "NULL",
1613
+ "expect": { "warehouse": null }
1614
+ },
1615
+ {
1616
+ "key": "clickhouse/Enum8('a' = 1, 'b' = 2)/plain",
1617
+ "native_type": "Enum8('a' = 1, 'b' = 2)",
1618
+ "class": "plain",
1619
+ "value_sql": "'b'",
1620
+ "expect": { "warehouse": "b" }
1621
+ },
1622
+ {
1623
+ "key": "clickhouse/Nullable(Enum8('a' = 1, 'b' = 2))/null",
1624
+ "native_type": "Nullable(Enum8('a' = 1, 'b' = 2))",
1625
+ "class": "null",
1626
+ "value_sql": "NULL",
1627
+ "expect": { "warehouse": null }
1628
+ },
1629
+ {
1630
+ "key": "clickhouse/UUID/plain",
1631
+ "native_type": "UUID",
1632
+ "class": "plain",
1633
+ "value_sql": "'00000000-0000-4000-8000-000000000001'",
1634
+ "expect": { "warehouse": "00000000-0000-4000-8000-000000000001" }
1635
+ },
1636
+ {
1637
+ "key": "clickhouse/Nullable(UUID)/null",
1638
+ "native_type": "Nullable(UUID)",
1639
+ "class": "null",
1640
+ "value_sql": "NULL",
1641
+ "expect": { "warehouse": null }
1642
+ },
1643
+ {
1644
+ "key": "clickhouse/IPv4/plain",
1645
+ "native_type": "IPv4",
1646
+ "class": "plain",
1647
+ "value_sql": "'10.0.0.1'",
1648
+ "expect": { "warehouse": "10.0.0.1" }
1649
+ },
1650
+ {
1651
+ "key": "clickhouse/Nullable(IPv4)/null",
1652
+ "native_type": "Nullable(IPv4)",
1653
+ "class": "null",
1654
+ "value_sql": "NULL",
1655
+ "expect": { "warehouse": null }
1656
+ },
1657
+ {
1658
+ "key": "clickhouse/IPv6/plain",
1659
+ "native_type": "IPv6",
1660
+ "class": "plain",
1661
+ "value_sql": "'2001:db8::1'",
1662
+ "expect": { "warehouse": "2001:db8::1" }
1663
+ },
1664
+ {
1665
+ "key": "clickhouse/Nullable(IPv6)/null",
1666
+ "native_type": "Nullable(IPv6)",
1667
+ "class": "null",
1668
+ "value_sql": "NULL",
1669
+ "expect": { "warehouse": null }
1670
+ },
1671
+ {
1672
+ "key": "clickhouse/JSON/nested_json",
1673
+ "native_type": "JSON",
1674
+ "class": "nested_json",
1675
+ "value_sql": "'{\"a\":{\"b\":\"x\",\"n\":1.5}}'",
1676
+ "expect": { "warehouse": { "a": {
1677
+ "b": "x",
1678
+ "n": 1.5
1679
+ } } }
1680
+ },
1681
+ {
1682
+ "key": "clickhouse/JSON/empty",
1683
+ "native_type": "JSON",
1684
+ "class": "empty",
1685
+ "value_sql": "'{}'",
1686
+ "expect": { "warehouse": {} }
1687
+ },
1688
+ {
1689
+ "key": "clickhouse/Array(Int32)/array",
1690
+ "native_type": "Array(Int32)",
1691
+ "class": "array",
1692
+ "value_sql": "[1, -2, 3]",
1693
+ "expect": { "warehouse": [
1694
+ 1,
1695
+ -2,
1696
+ 3
1697
+ ] }
1698
+ },
1699
+ {
1700
+ "key": "clickhouse/Array(Int32)/empty",
1701
+ "native_type": "Array(Int32)",
1702
+ "class": "empty",
1703
+ "value_sql": "[]",
1704
+ "expect": { "warehouse": [] }
1705
+ },
1706
+ {
1707
+ "key": "clickhouse/Array(Nullable(String))/array",
1708
+ "native_type": "Array(Nullable(String))",
1709
+ "class": "array",
1710
+ "value_sql": "['a', NULL]",
1711
+ "expect": { "warehouse": ["a", null] }
1712
+ },
1713
+ {
1714
+ "key": "clickhouse/Tuple(Int32, String)/array",
1715
+ "native_type": "Tuple(Int32, String)",
1716
+ "class": "array",
1717
+ "value_sql": "(1, 'a')",
1718
+ "expect": { "warehouse": [1, "a"] }
1719
+ },
1720
+ {
1721
+ "key": "clickhouse/Map(String, Int32)/nested_json",
1722
+ "native_type": "Map(String, Int32)",
1723
+ "class": "nested_json",
1724
+ "value_sql": "map('a', 1, 'b', 2)",
1725
+ "expect": { "warehouse": {
1726
+ "a": 1,
1727
+ "b": 2
1728
+ } }
1729
+ },
1730
+ {
1731
+ "key": "clickhouse/Map(String, Int32)/empty",
1732
+ "native_type": "Map(String, Int32)",
1733
+ "class": "empty",
1734
+ "value_sql": "map()",
1735
+ "expect": { "warehouse": {} }
1736
+ },
1737
+ {
1738
+ "key": "clickhouse/SimpleAggregateFunction(sum, UInt64)/plain",
1739
+ "native_type": "SimpleAggregateFunction(sum, UInt64)",
1740
+ "class": "plain",
1741
+ "value_sql": "3",
1742
+ "expect": { "warehouse": 3 }
1743
+ },
1744
+ {
1745
+ "key": "clickhouse/AggregateFunction(sum, UInt64)/plain",
1746
+ "native_type": "AggregateFunction(sum, UInt64)",
1747
+ "class": "plain",
1748
+ "value_sql": "arrayReduce('sumState', [toUInt64(3)])",
1749
+ "expect": { "warehouse": "\0\0\0\0\0\0\0" }
1750
+ }
1751
+ ] },
1752
+ "postgres": { "cases": [
1753
+ {
1754
+ "key": "postgres/bool/plain",
1755
+ "native_type": "bool",
1756
+ "class": "plain",
1757
+ "value_sql": "true",
1758
+ "expect": {
1759
+ "warehouse": true,
1760
+ "oltp": true
1761
+ }
1762
+ },
1763
+ {
1764
+ "key": "postgres/bool/null",
1765
+ "native_type": "bool",
1766
+ "class": "null",
1767
+ "value_sql": "NULL",
1768
+ "expect": {
1769
+ "warehouse": null,
1770
+ "oltp": null
1771
+ }
1772
+ },
1773
+ {
1774
+ "key": "postgres/int2/plain",
1775
+ "native_type": "int2",
1776
+ "class": "plain",
1777
+ "value_sql": "42",
1778
+ "expect": {
1779
+ "warehouse": 42,
1780
+ "oltp": 42
1781
+ }
1782
+ },
1783
+ {
1784
+ "key": "postgres/int2/negative",
1785
+ "native_type": "int2",
1786
+ "class": "negative",
1787
+ "value_sql": "-32768",
1788
+ "expect": {
1789
+ "warehouse": -32768,
1790
+ "oltp": -32768
1791
+ }
1792
+ },
1793
+ {
1794
+ "key": "postgres/int2/zero",
1795
+ "native_type": "int2",
1796
+ "class": "zero",
1797
+ "value_sql": "0",
1798
+ "expect": {
1799
+ "warehouse": 0,
1800
+ "oltp": 0
1801
+ }
1802
+ },
1803
+ {
1804
+ "key": "postgres/int2/null",
1805
+ "native_type": "int2",
1806
+ "class": "null",
1807
+ "value_sql": "NULL",
1808
+ "expect": {
1809
+ "warehouse": null,
1810
+ "oltp": null
1811
+ }
1812
+ },
1813
+ {
1814
+ "key": "postgres/int4/plain",
1815
+ "native_type": "int4",
1816
+ "class": "plain",
1817
+ "value_sql": "42",
1818
+ "expect": {
1819
+ "warehouse": 42,
1820
+ "oltp": 42
1821
+ }
1822
+ },
1823
+ {
1824
+ "key": "postgres/int4/negative",
1825
+ "native_type": "int4",
1826
+ "class": "negative",
1827
+ "value_sql": "-2147483648",
1828
+ "expect": {
1829
+ "warehouse": -2147483648,
1830
+ "oltp": -2147483648
1831
+ }
1832
+ },
1833
+ {
1834
+ "key": "postgres/int4/zero",
1835
+ "native_type": "int4",
1836
+ "class": "zero",
1837
+ "value_sql": "0",
1838
+ "expect": {
1839
+ "warehouse": 0,
1840
+ "oltp": 0
1841
+ }
1842
+ },
1843
+ {
1844
+ "key": "postgres/int4/null",
1845
+ "native_type": "int4",
1846
+ "class": "null",
1847
+ "value_sql": "NULL",
1848
+ "expect": {
1849
+ "warehouse": null,
1850
+ "oltp": null
1851
+ }
1852
+ },
1853
+ {
1854
+ "key": "postgres/int8/plain",
1855
+ "native_type": "int8",
1856
+ "class": "plain",
1857
+ "value_sql": "42",
1858
+ "expect": {
1859
+ "warehouse": 42,
1860
+ "oltp": 42
1861
+ }
1862
+ },
1863
+ {
1864
+ "key": "postgres/int8/negative",
1865
+ "native_type": "int8",
1866
+ "class": "negative",
1867
+ "value_sql": "-9007199254740991",
1868
+ "expect": {
1869
+ "warehouse": -9007199254740991,
1870
+ "oltp": -9007199254740991
1871
+ }
1872
+ },
1873
+ {
1874
+ "key": "postgres/int8/zero",
1875
+ "native_type": "int8",
1876
+ "class": "zero",
1877
+ "value_sql": "0",
1878
+ "expect": {
1879
+ "warehouse": 0,
1880
+ "oltp": 0
1881
+ }
1882
+ },
1883
+ {
1884
+ "key": "postgres/int8/precision_gt_18",
1885
+ "native_type": "int8",
1886
+ "class": "precision_gt_18",
1887
+ "value_sql": "9223372036854775807",
1888
+ "expect": {
1889
+ "warehouse": 0x8000000000000000,
1890
+ "oltp": 0x8000000000000000
1891
+ }
1892
+ },
1893
+ {
1894
+ "key": "postgres/int8/null",
1895
+ "native_type": "int8",
1896
+ "class": "null",
1897
+ "value_sql": "NULL",
1898
+ "expect": {
1899
+ "warehouse": null,
1900
+ "oltp": null
1901
+ }
1902
+ },
1903
+ {
1904
+ "key": "postgres/float4/plain",
1905
+ "native_type": "float4",
1906
+ "class": "plain",
1907
+ "value_sql": "0.1",
1908
+ "expect": {
1909
+ "warehouse": .10000000149011612,
1910
+ "oltp": .10000000149011612
1911
+ }
1912
+ },
1913
+ {
1914
+ "key": "postgres/float4/negative",
1915
+ "native_type": "float4",
1916
+ "class": "negative",
1917
+ "value_sql": "-1.5",
1918
+ "expect": {
1919
+ "warehouse": -1.5,
1920
+ "oltp": -1.5
1921
+ }
1922
+ },
1923
+ {
1924
+ "key": "postgres/float4/zero",
1925
+ "native_type": "float4",
1926
+ "class": "zero",
1927
+ "value_sql": "0",
1928
+ "expect": {
1929
+ "warehouse": 0,
1930
+ "oltp": 0
1931
+ }
1932
+ },
1933
+ {
1934
+ "key": "postgres/float4/nan_inf",
1935
+ "native_type": "float4",
1936
+ "class": "nan_inf",
1937
+ "value_sql": "'NaN'",
1938
+ "expect": {
1939
+ "warehouse": null,
1940
+ "oltp": null
1941
+ }
1942
+ },
1943
+ {
1944
+ "key": "postgres/float4/null",
1945
+ "native_type": "float4",
1946
+ "class": "null",
1947
+ "value_sql": "NULL",
1948
+ "expect": {
1949
+ "warehouse": null,
1950
+ "oltp": null
1951
+ }
1952
+ },
1953
+ {
1954
+ "key": "postgres/float8/plain",
1955
+ "native_type": "float8",
1956
+ "class": "plain",
1957
+ "value_sql": "0.1",
1958
+ "expect": {
1959
+ "warehouse": .1,
1960
+ "oltp": .1
1961
+ }
1962
+ },
1963
+ {
1964
+ "key": "postgres/float8/negative",
1965
+ "native_type": "float8",
1966
+ "class": "negative",
1967
+ "value_sql": "-1.5",
1968
+ "expect": {
1969
+ "warehouse": -1.5,
1970
+ "oltp": -1.5
1971
+ }
1972
+ },
1973
+ {
1974
+ "key": "postgres/float8/zero",
1975
+ "native_type": "float8",
1976
+ "class": "zero",
1977
+ "value_sql": "0",
1978
+ "expect": {
1979
+ "warehouse": 0,
1980
+ "oltp": 0
1981
+ }
1982
+ },
1983
+ {
1984
+ "key": "postgres/float8/nan_inf",
1985
+ "native_type": "float8",
1986
+ "class": "nan_inf",
1987
+ "value_sql": "'Infinity'",
1988
+ "expect": {
1989
+ "warehouse": null,
1990
+ "oltp": null
1991
+ }
1992
+ },
1993
+ {
1994
+ "key": "postgres/float8/null",
1995
+ "native_type": "float8",
1996
+ "class": "null",
1997
+ "value_sql": "NULL",
1998
+ "expect": {
1999
+ "warehouse": null,
2000
+ "oltp": null
2001
+ }
2002
+ },
2003
+ {
2004
+ "key": "postgres/numeric/plain",
2005
+ "native_type": "numeric",
2006
+ "class": "plain",
2007
+ "value_sql": "1234.5678",
2008
+ "expect": {
2009
+ "warehouse": "1234.5678",
2010
+ "oltp": { "$error": "Postgres type `numeric`, which cannot be returned directly" }
2011
+ }
2012
+ },
2013
+ {
2014
+ "key": "postgres/numeric/negative",
2015
+ "native_type": "numeric",
2016
+ "class": "negative",
2017
+ "value_sql": "-1.25",
2018
+ "expect": {
2019
+ "warehouse": "-1.25",
2020
+ "oltp": { "$error": "Postgres type `numeric`, which cannot be returned directly" }
2021
+ }
2022
+ },
2023
+ {
2024
+ "key": "postgres/numeric/zero",
2025
+ "native_type": "numeric",
2026
+ "class": "zero",
2027
+ "value_sql": "0",
2028
+ "expect": {
2029
+ "warehouse": "0.0",
2030
+ "oltp": { "$error": "Postgres type `numeric`, which cannot be returned directly" }
2031
+ }
2032
+ },
2033
+ {
2034
+ "key": "postgres/numeric/nan_inf",
2035
+ "native_type": "numeric",
2036
+ "class": "nan_inf",
2037
+ "value_sql": "'NaN'",
2038
+ "expect": {
2039
+ "warehouse": "NaN",
2040
+ "oltp": { "$error": "Postgres type `numeric`, which cannot be returned directly" }
2041
+ }
2042
+ },
2043
+ {
2044
+ "key": "postgres/numeric/precision_gt_18",
2045
+ "native_type": "numeric",
2046
+ "class": "precision_gt_18",
2047
+ "value_sql": "1234567890123456789.0123456789",
2048
+ "expect": {
2049
+ "warehouse": "1234567890123456768.0",
2050
+ "oltp": { "$error": "Postgres type `numeric`, which cannot be returned directly" }
2051
+ }
2052
+ },
2053
+ {
2054
+ "key": "postgres/numeric/null",
2055
+ "native_type": "numeric",
2056
+ "class": "null",
2057
+ "value_sql": "NULL",
2058
+ "expect": {
2059
+ "warehouse": null,
2060
+ "oltp": { "$error": "Postgres type `numeric`, which cannot be returned directly" }
2061
+ }
2062
+ },
2063
+ {
2064
+ "key": "postgres/text/plain",
2065
+ "native_type": "text",
2066
+ "class": "plain",
2067
+ "value_sql": "'plain text'",
2068
+ "expect": {
2069
+ "warehouse": "plain text",
2070
+ "oltp": "plain text"
2071
+ }
2072
+ },
2073
+ {
2074
+ "key": "postgres/text/empty",
2075
+ "native_type": "text",
2076
+ "class": "empty",
2077
+ "value_sql": "''",
2078
+ "expect": {
2079
+ "warehouse": "",
2080
+ "oltp": ""
2081
+ }
2082
+ },
2083
+ {
2084
+ "key": "postgres/text/whitespace",
2085
+ "native_type": "text",
2086
+ "class": "whitespace",
2087
+ "value_sql": "E' \\t\\n '",
2088
+ "expect": {
2089
+ "warehouse": " \n ",
2090
+ "oltp": " \n "
2091
+ }
2092
+ },
2093
+ {
2094
+ "key": "postgres/text/non_bmp",
2095
+ "native_type": "text",
2096
+ "class": "non_bmp",
2097
+ "value_sql": "'𝔘nicode'",
2098
+ "expect": {
2099
+ "warehouse": "𝔘nicode",
2100
+ "oltp": "𝔘nicode"
2101
+ }
2102
+ },
2103
+ {
2104
+ "key": "postgres/text/len_gt_1k",
2105
+ "native_type": "text",
2106
+ "class": "len_gt_1k",
2107
+ "value_sql": "repeat('0123456789', 101)",
2108
+ "expect": {
2109
+ "warehouse": "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
2110
+ "oltp": "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
2111
+ }
2112
+ },
2113
+ {
2114
+ "key": "postgres/text/null",
2115
+ "native_type": "text",
2116
+ "class": "null",
2117
+ "value_sql": "NULL",
2118
+ "expect": {
2119
+ "warehouse": null,
2120
+ "oltp": null
2121
+ }
2122
+ },
2123
+ {
2124
+ "key": "postgres/varchar(2000)/plain",
2125
+ "native_type": "varchar(2000)",
2126
+ "class": "plain",
2127
+ "value_sql": "'plain varchar'",
2128
+ "expect": {
2129
+ "warehouse": "plain varchar",
2130
+ "oltp": "plain varchar"
2131
+ }
2132
+ },
2133
+ {
2134
+ "key": "postgres/varchar(2000)/empty",
2135
+ "native_type": "varchar(2000)",
2136
+ "class": "empty",
2137
+ "value_sql": "''",
2138
+ "expect": {
2139
+ "warehouse": "",
2140
+ "oltp": ""
2141
+ }
2142
+ },
2143
+ {
2144
+ "key": "postgres/varchar(2000)/whitespace",
2145
+ "native_type": "varchar(2000)",
2146
+ "class": "whitespace",
2147
+ "value_sql": "E' \\t\\n '",
2148
+ "expect": {
2149
+ "warehouse": " \n ",
2150
+ "oltp": " \n "
2151
+ }
2152
+ },
2153
+ {
2154
+ "key": "postgres/varchar(2000)/non_bmp",
2155
+ "native_type": "varchar(2000)",
2156
+ "class": "non_bmp",
2157
+ "value_sql": "'𝔘nicode'",
2158
+ "expect": {
2159
+ "warehouse": "𝔘nicode",
2160
+ "oltp": "𝔘nicode"
2161
+ }
2162
+ },
2163
+ {
2164
+ "key": "postgres/varchar(2000)/len_gt_1k",
2165
+ "native_type": "varchar(2000)",
2166
+ "class": "len_gt_1k",
2167
+ "value_sql": "repeat('0123456789', 101)",
2168
+ "expect": {
2169
+ "warehouse": "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
2170
+ "oltp": "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
2171
+ }
2172
+ },
2173
+ {
2174
+ "key": "postgres/varchar(2000)/null",
2175
+ "native_type": "varchar(2000)",
2176
+ "class": "null",
2177
+ "value_sql": "NULL",
2178
+ "expect": {
2179
+ "warehouse": null,
2180
+ "oltp": null
2181
+ }
2182
+ },
2183
+ {
2184
+ "key": "postgres/bpchar(8)/plain",
2185
+ "native_type": "bpchar(8)",
2186
+ "class": "plain",
2187
+ "value_sql": "'ab'",
2188
+ "expect": {
2189
+ "warehouse": "ab ",
2190
+ "oltp": "ab "
2191
+ }
2192
+ },
2193
+ {
2194
+ "key": "postgres/bpchar(8)/empty",
2195
+ "native_type": "bpchar(8)",
2196
+ "class": "empty",
2197
+ "value_sql": "''",
2198
+ "expect": {
2199
+ "warehouse": " ",
2200
+ "oltp": " "
2201
+ }
2202
+ },
2203
+ {
2204
+ "key": "postgres/bpchar(8)/whitespace",
2205
+ "native_type": "bpchar(8)",
2206
+ "class": "whitespace",
2207
+ "value_sql": "E' \\t\\n '",
2208
+ "expect": {
2209
+ "warehouse": " \n ",
2210
+ "oltp": " \n "
2211
+ }
2212
+ },
2213
+ {
2214
+ "key": "postgres/bpchar(8)/non_bmp",
2215
+ "native_type": "bpchar(8)",
2216
+ "class": "non_bmp",
2217
+ "value_sql": "'𝔘'",
2218
+ "expect": {
2219
+ "warehouse": "𝔘 ",
2220
+ "oltp": "𝔘 "
2221
+ }
2222
+ },
2223
+ {
2224
+ "key": "postgres/bpchar(8)/null",
2225
+ "native_type": "bpchar(8)",
2226
+ "class": "null",
2227
+ "value_sql": "NULL",
2228
+ "expect": {
2229
+ "warehouse": null,
2230
+ "oltp": null
2231
+ }
2232
+ },
2233
+ {
2234
+ "key": "postgres/\"char\"/plain",
2235
+ "native_type": "\"char\"",
2236
+ "class": "plain",
2237
+ "value_sql": "'a'",
2238
+ "expect": {
2239
+ "warehouse": "a",
2240
+ "oltp": { "$error": "Postgres type `char`, which cannot be returned directly" }
2241
+ }
2242
+ },
2243
+ {
2244
+ "key": "postgres/\"char\"/null",
2245
+ "native_type": "\"char\"",
2246
+ "class": "null",
2247
+ "value_sql": "NULL",
2248
+ "expect": {
2249
+ "warehouse": null,
2250
+ "oltp": { "$error": "Postgres type `char`, which cannot be returned directly" }
2251
+ }
2252
+ },
2253
+ {
2254
+ "key": "postgres/name/plain",
2255
+ "native_type": "name",
2256
+ "class": "plain",
2257
+ "value_sql": "'plain_name'",
2258
+ "expect": {
2259
+ "warehouse": "plain_name",
2260
+ "oltp": "plain_name"
2261
+ }
2262
+ },
2263
+ {
2264
+ "key": "postgres/name/empty",
2265
+ "native_type": "name",
2266
+ "class": "empty",
2267
+ "value_sql": "''",
2268
+ "expect": {
2269
+ "warehouse": "",
2270
+ "oltp": ""
2271
+ }
2272
+ },
2273
+ {
2274
+ "key": "postgres/name/len_gt_1k",
2275
+ "native_type": "name",
2276
+ "class": "len_gt_1k",
2277
+ "value_sql": "repeat('0123456789', 101)",
2278
+ "expect": {
2279
+ "warehouse": "012345678901234567890123456789012345678901234567890123456789012",
2280
+ "oltp": "012345678901234567890123456789012345678901234567890123456789012"
2281
+ }
2282
+ },
2283
+ {
2284
+ "key": "postgres/name/null",
2285
+ "native_type": "name",
2286
+ "class": "null",
2287
+ "value_sql": "NULL",
2288
+ "expect": {
2289
+ "warehouse": null,
2290
+ "oltp": null
2291
+ }
2292
+ },
2293
+ {
2294
+ "key": "postgres/bytea/plain",
2295
+ "native_type": "bytea",
2296
+ "class": "plain",
2297
+ "value_sql": "decode('0001ff', 'hex')",
2298
+ "expect": {
2299
+ "warehouse": "<3 bytes>",
2300
+ "oltp": { "$error": "Postgres type `bytea`, which cannot be returned directly" }
2301
+ }
2302
+ },
2303
+ {
2304
+ "key": "postgres/bytea/empty",
2305
+ "native_type": "bytea",
2306
+ "class": "empty",
2307
+ "value_sql": "decode('', 'hex')",
2308
+ "expect": {
2309
+ "warehouse": "<0 bytes>",
2310
+ "oltp": { "$error": "Postgres type `bytea`, which cannot be returned directly" }
2311
+ }
2312
+ },
2313
+ {
2314
+ "key": "postgres/bytea/null",
2315
+ "native_type": "bytea",
2316
+ "class": "null",
2317
+ "value_sql": "NULL",
2318
+ "expect": {
2319
+ "warehouse": null,
2320
+ "oltp": { "$error": "Postgres type `bytea`, which cannot be returned directly" }
2321
+ }
2322
+ },
2323
+ {
2324
+ "key": "postgres/date/plain",
2325
+ "native_type": "date",
2326
+ "class": "plain",
2327
+ "value_sql": "DATE '2024-03-10'",
2328
+ "expect": {
2329
+ "warehouse": "2024-03-10",
2330
+ "oltp": "2024-03-10"
2331
+ }
2332
+ },
2333
+ {
2334
+ "key": "postgres/date/date_before_1970",
2335
+ "native_type": "date",
2336
+ "class": "date_before_1970",
2337
+ "value_sql": "DATE '1969-12-31'",
2338
+ "expect": {
2339
+ "warehouse": "1969-12-31",
2340
+ "oltp": "1969-12-31"
2341
+ }
2342
+ },
2343
+ {
2344
+ "key": "postgres/date/date_after_2100",
2345
+ "native_type": "date",
2346
+ "class": "date_after_2100",
2347
+ "value_sql": "DATE '2150-06-01'",
2348
+ "expect": {
2349
+ "warehouse": "2150-06-01",
2350
+ "oltp": "2150-06-01"
2351
+ }
2352
+ },
2353
+ {
2354
+ "key": "postgres/date/null",
2355
+ "native_type": "date",
2356
+ "class": "null",
2357
+ "value_sql": "NULL",
2358
+ "expect": {
2359
+ "warehouse": null,
2360
+ "oltp": null
2361
+ }
2362
+ },
2363
+ {
2364
+ "key": "postgres/timestamp/plain",
2365
+ "native_type": "timestamp",
2366
+ "class": "plain",
2367
+ "value_sql": "TIMESTAMP '2024-03-10 12:34:56.789'",
2368
+ "expect": {
2369
+ "warehouse": "2024-03-10 12:34:56.789000",
2370
+ "oltp": "2024-03-10T12:34:56.789000"
2371
+ }
2372
+ },
2373
+ {
2374
+ "key": "postgres/timestamp/date_before_1970",
2375
+ "native_type": "timestamp",
2376
+ "class": "date_before_1970",
2377
+ "value_sql": "TIMESTAMP '1969-07-20 20:17:40.5'",
2378
+ "expect": {
2379
+ "warehouse": "1969-07-20 20:17:40.500000",
2380
+ "oltp": "1969-07-20T20:17:40.500000"
2381
+ }
2382
+ },
2383
+ {
2384
+ "key": "postgres/timestamp/date_after_2100",
2385
+ "native_type": "timestamp",
2386
+ "class": "date_after_2100",
2387
+ "value_sql": "TIMESTAMP '2150-01-01 00:00:00'",
2388
+ "expect": {
2389
+ "warehouse": "2150-01-01 00:00:00",
2390
+ "oltp": "2150-01-01T00:00:00.000000"
2391
+ }
2392
+ },
2393
+ {
2394
+ "key": "postgres/timestamp/null",
2395
+ "native_type": "timestamp",
2396
+ "class": "null",
2397
+ "value_sql": "NULL",
2398
+ "expect": {
2399
+ "warehouse": null,
2400
+ "oltp": null
2401
+ }
2402
+ },
2403
+ {
2404
+ "key": "postgres/timestamptz/plain",
2405
+ "native_type": "timestamptz",
2406
+ "class": "plain",
2407
+ "value_sql": "TIMESTAMPTZ '2024-03-10 12:34:56.789+00'",
2408
+ "expect": {
2409
+ "warehouse": "2024-03-10 12:34:56.789000",
2410
+ "oltp": "2024-03-10T12:34:56.789000Z"
2411
+ }
2412
+ },
2413
+ {
2414
+ "key": "postgres/timestamptz/tz_bearing",
2415
+ "native_type": "timestamptz",
2416
+ "class": "tz_bearing",
2417
+ "value_sql": "TIMESTAMPTZ '2024-03-10 12:34:56+05:30'",
2418
+ "expect": {
2419
+ "warehouse": "2024-03-10 07:04:56",
2420
+ "oltp": "2024-03-10T07:04:56.000000Z"
2421
+ }
2422
+ },
2423
+ {
2424
+ "key": "postgres/timestamptz/date_before_1970",
2425
+ "native_type": "timestamptz",
2426
+ "class": "date_before_1970",
2427
+ "value_sql": "TIMESTAMPTZ '1969-07-20 20:17:40.5+00'",
2428
+ "expect": {
2429
+ "warehouse": "1969-07-20 20:17:40.500000",
2430
+ "oltp": "1969-07-20T20:17:40.500000Z"
2431
+ }
2432
+ },
2433
+ {
2434
+ "key": "postgres/timestamptz/date_after_2100",
2435
+ "native_type": "timestamptz",
2436
+ "class": "date_after_2100",
2437
+ "value_sql": "TIMESTAMPTZ '2150-01-01 00:00:00+00'",
2438
+ "expect": {
2439
+ "warehouse": "2150-01-01 00:00:00",
2440
+ "oltp": "2150-01-01T00:00:00.000000Z"
2441
+ }
2442
+ },
2443
+ {
2444
+ "key": "postgres/timestamptz/null",
2445
+ "native_type": "timestamptz",
2446
+ "class": "null",
2447
+ "value_sql": "NULL",
2448
+ "expect": {
2449
+ "warehouse": null,
2450
+ "oltp": null
2451
+ }
2452
+ },
2453
+ {
2454
+ "key": "postgres/time/plain",
2455
+ "native_type": "time",
2456
+ "class": "plain",
2457
+ "value_sql": "TIME '12:34:56.789'",
2458
+ "expect": {
2459
+ "warehouse": "12:34:56.789",
2460
+ "oltp": "12:34:56.789000"
2461
+ }
2462
+ },
2463
+ {
2464
+ "key": "postgres/time/null",
2465
+ "native_type": "time",
2466
+ "class": "null",
2467
+ "value_sql": "NULL",
2468
+ "expect": {
2469
+ "warehouse": null,
2470
+ "oltp": null
2471
+ }
2472
+ },
2473
+ {
2474
+ "key": "postgres/json/nested_json",
2475
+ "native_type": "json",
2476
+ "class": "nested_json",
2477
+ "value_sql": "'{\"a\":{\"b\":[1,2]},\"s\":\"x\"}'",
2478
+ "expect": {
2479
+ "warehouse": {
2480
+ "a": { "b": [1, 2] },
2481
+ "s": "x"
2482
+ },
2483
+ "oltp": {
2484
+ "a": { "b": [1, 2] },
2485
+ "s": "x"
2486
+ }
2487
+ }
2488
+ },
2489
+ {
2490
+ "key": "postgres/json/null",
2491
+ "native_type": "json",
2492
+ "class": "null",
2493
+ "value_sql": "NULL",
2494
+ "expect": {
2495
+ "warehouse": null,
2496
+ "oltp": null
2497
+ }
2498
+ },
2499
+ {
2500
+ "key": "postgres/jsonb/nested_json",
2501
+ "native_type": "jsonb",
2502
+ "class": "nested_json",
2503
+ "value_sql": "'{\"a\":{\"b\":[1,2]},\"s\":\"x\"}'",
2504
+ "expect": {
2505
+ "warehouse": {
2506
+ "a": { "b": [1, 2] },
2507
+ "s": "x"
2508
+ },
2509
+ "oltp": {
2510
+ "a": { "b": [1, 2] },
2511
+ "s": "x"
2512
+ }
2513
+ }
2514
+ },
2515
+ {
2516
+ "key": "postgres/jsonb/array",
2517
+ "native_type": "jsonb",
2518
+ "class": "array",
2519
+ "value_sql": "'[1,\"two\",null]'",
2520
+ "expect": {
2521
+ "warehouse": [
2522
+ 1,
2523
+ "two",
2524
+ null
2525
+ ],
2526
+ "oltp": [
2527
+ 1,
2528
+ "two",
2529
+ null
2530
+ ]
2531
+ }
2532
+ },
2533
+ {
2534
+ "key": "postgres/jsonb/null",
2535
+ "native_type": "jsonb",
2536
+ "class": "null",
2537
+ "value_sql": "NULL",
2538
+ "expect": {
2539
+ "warehouse": null,
2540
+ "oltp": null
2541
+ }
2542
+ },
2543
+ {
2544
+ "key": "postgres/uuid/plain",
2545
+ "native_type": "uuid",
2546
+ "class": "plain",
2547
+ "value_sql": "'00000000-0000-4000-8000-000000000001'",
2548
+ "expect": {
2549
+ "warehouse": "00000000-0000-4000-8000-000000000001",
2550
+ "oltp": "00000000-0000-4000-8000-000000000001"
2551
+ }
2552
+ },
2553
+ {
2554
+ "key": "postgres/uuid/null",
2555
+ "native_type": "uuid",
2556
+ "class": "null",
2557
+ "value_sql": "NULL",
2558
+ "expect": {
2559
+ "warehouse": null,
2560
+ "oltp": null
2561
+ }
2562
+ },
2563
+ {
2564
+ "key": "postgres/int4[]/array",
2565
+ "native_type": "int4[]",
2566
+ "class": "array",
2567
+ "value_sql": "ARRAY[1, -2, 3]",
2568
+ "expect": {
2569
+ "warehouse": "{1,-2,3}",
2570
+ "oltp": { "$error": "Postgres type `_int4`, which cannot be returned directly" }
2571
+ }
2572
+ },
2573
+ {
2574
+ "key": "postgres/int4[]/empty",
2575
+ "native_type": "int4[]",
2576
+ "class": "empty",
2577
+ "value_sql": "'{}'",
2578
+ "expect": {
2579
+ "warehouse": "{}",
2580
+ "oltp": { "$error": "Postgres type `_int4`, which cannot be returned directly" }
2581
+ }
2582
+ }
2583
+ ] },
2584
+ "duckdb": { "cases": [
2585
+ {
2586
+ "key": "duckdb/BOOLEAN/plain",
2587
+ "native_type": "BOOLEAN",
2588
+ "class": "plain",
2589
+ "value_sql": "true",
2590
+ "expect": { "warehouse": true }
2591
+ },
2592
+ {
2593
+ "key": "duckdb/BOOLEAN/null",
2594
+ "native_type": "BOOLEAN",
2595
+ "class": "null",
2596
+ "value_sql": "NULL",
2597
+ "expect": { "warehouse": null }
2598
+ },
2599
+ {
2600
+ "key": "duckdb/BOOL/plain",
2601
+ "native_type": "BOOL",
2602
+ "class": "plain",
2603
+ "value_sql": "false",
2604
+ "expect": { "warehouse": false }
2605
+ },
2606
+ {
2607
+ "key": "duckdb/TINYINT/plain",
2608
+ "native_type": "TINYINT",
2609
+ "class": "plain",
2610
+ "value_sql": "42",
2611
+ "expect": { "warehouse": 42 }
2612
+ },
2613
+ {
2614
+ "key": "duckdb/TINYINT/negative",
2615
+ "native_type": "TINYINT",
2616
+ "class": "negative",
2617
+ "value_sql": "-128",
2618
+ "expect": { "warehouse": -128 }
2619
+ },
2620
+ {
2621
+ "key": "duckdb/TINYINT/zero",
2622
+ "native_type": "TINYINT",
2623
+ "class": "zero",
2624
+ "value_sql": "0",
2625
+ "expect": { "warehouse": 0 }
2626
+ },
2627
+ {
2628
+ "key": "duckdb/TINYINT/null",
2629
+ "native_type": "TINYINT",
2630
+ "class": "null",
2631
+ "value_sql": "NULL",
2632
+ "expect": { "warehouse": null }
2633
+ },
2634
+ {
2635
+ "key": "duckdb/INT1/plain",
2636
+ "native_type": "INT1",
2637
+ "class": "plain",
2638
+ "value_sql": "42",
2639
+ "expect": { "warehouse": 42 }
2640
+ },
2641
+ {
2642
+ "key": "duckdb/SMALLINT/plain",
2643
+ "native_type": "SMALLINT",
2644
+ "class": "plain",
2645
+ "value_sql": "42",
2646
+ "expect": { "warehouse": 42 }
2647
+ },
2648
+ {
2649
+ "key": "duckdb/SMALLINT/negative",
2650
+ "native_type": "SMALLINT",
2651
+ "class": "negative",
2652
+ "value_sql": "-32768",
2653
+ "expect": { "warehouse": -32768 }
2654
+ },
2655
+ {
2656
+ "key": "duckdb/SMALLINT/zero",
2657
+ "native_type": "SMALLINT",
2658
+ "class": "zero",
2659
+ "value_sql": "0",
2660
+ "expect": { "warehouse": 0 }
2661
+ },
2662
+ {
2663
+ "key": "duckdb/SMALLINT/null",
2664
+ "native_type": "SMALLINT",
2665
+ "class": "null",
2666
+ "value_sql": "NULL",
2667
+ "expect": { "warehouse": null }
2668
+ },
2669
+ {
2670
+ "key": "duckdb/INT2/plain",
2671
+ "native_type": "INT2",
2672
+ "class": "plain",
2673
+ "value_sql": "42",
2674
+ "expect": { "warehouse": 42 }
2675
+ },
2676
+ {
2677
+ "key": "duckdb/INTEGER/plain",
2678
+ "native_type": "INTEGER",
2679
+ "class": "plain",
2680
+ "value_sql": "42",
2681
+ "expect": { "warehouse": 42 }
2682
+ },
2683
+ {
2684
+ "key": "duckdb/INTEGER/negative",
2685
+ "native_type": "INTEGER",
2686
+ "class": "negative",
2687
+ "value_sql": "-2147483648",
2688
+ "expect": { "warehouse": -2147483648 }
2689
+ },
2690
+ {
2691
+ "key": "duckdb/INTEGER/zero",
2692
+ "native_type": "INTEGER",
2693
+ "class": "zero",
2694
+ "value_sql": "0",
2695
+ "expect": { "warehouse": 0 }
2696
+ },
2697
+ {
2698
+ "key": "duckdb/INTEGER/null",
2699
+ "native_type": "INTEGER",
2700
+ "class": "null",
2701
+ "value_sql": "NULL",
2702
+ "expect": { "warehouse": null }
2703
+ },
2704
+ {
2705
+ "key": "duckdb/INT/plain",
2706
+ "native_type": "INT",
2707
+ "class": "plain",
2708
+ "value_sql": "42",
2709
+ "expect": { "warehouse": 42 }
2710
+ },
2711
+ {
2712
+ "key": "duckdb/INT4/plain",
2713
+ "native_type": "INT4",
2714
+ "class": "plain",
2715
+ "value_sql": "42",
2716
+ "expect": { "warehouse": 42 }
2717
+ },
2718
+ {
2719
+ "key": "duckdb/BIGINT/plain",
2720
+ "native_type": "BIGINT",
2721
+ "class": "plain",
2722
+ "value_sql": "42",
2723
+ "expect": { "warehouse": 42 }
2724
+ },
2725
+ {
2726
+ "key": "duckdb/BIGINT/negative",
2727
+ "native_type": "BIGINT",
2728
+ "class": "negative",
2729
+ "value_sql": "-9007199254740991",
2730
+ "expect": { "warehouse": -9007199254740991 }
2731
+ },
2732
+ {
2733
+ "key": "duckdb/BIGINT/zero",
2734
+ "native_type": "BIGINT",
2735
+ "class": "zero",
2736
+ "value_sql": "0",
2737
+ "expect": { "warehouse": 0 }
2738
+ },
2739
+ {
2740
+ "key": "duckdb/BIGINT/precision_gt_18",
2741
+ "native_type": "BIGINT",
2742
+ "class": "precision_gt_18",
2743
+ "value_sql": "9223372036854775807",
2744
+ "expect": { "warehouse": 0x8000000000000000 }
2745
+ },
2746
+ {
2747
+ "key": "duckdb/BIGINT/null",
2748
+ "native_type": "BIGINT",
2749
+ "class": "null",
2750
+ "value_sql": "NULL",
2751
+ "expect": { "warehouse": null }
2752
+ },
2753
+ {
2754
+ "key": "duckdb/INT8/plain",
2755
+ "native_type": "INT8",
2756
+ "class": "plain",
2757
+ "value_sql": "42",
2758
+ "expect": { "warehouse": 42 }
2759
+ },
2760
+ {
2761
+ "key": "duckdb/UTINYINT/plain",
2762
+ "native_type": "UTINYINT",
2763
+ "class": "plain",
2764
+ "value_sql": "42",
2765
+ "expect": { "warehouse": 42 }
2766
+ },
2767
+ {
2768
+ "key": "duckdb/UTINYINT/zero",
2769
+ "native_type": "UTINYINT",
2770
+ "class": "zero",
2771
+ "value_sql": "0",
2772
+ "expect": { "warehouse": 0 }
2773
+ },
2774
+ {
2775
+ "key": "duckdb/UTINYINT/null",
2776
+ "native_type": "UTINYINT",
2777
+ "class": "null",
2778
+ "value_sql": "NULL",
2779
+ "expect": { "warehouse": null }
2780
+ },
2781
+ {
2782
+ "key": "duckdb/USMALLINT/plain",
2783
+ "native_type": "USMALLINT",
2784
+ "class": "plain",
2785
+ "value_sql": "42",
2786
+ "expect": { "warehouse": 42 }
2787
+ },
2788
+ {
2789
+ "key": "duckdb/USMALLINT/zero",
2790
+ "native_type": "USMALLINT",
2791
+ "class": "zero",
2792
+ "value_sql": "0",
2793
+ "expect": { "warehouse": 0 }
2794
+ },
2795
+ {
2796
+ "key": "duckdb/USMALLINT/null",
2797
+ "native_type": "USMALLINT",
2798
+ "class": "null",
2799
+ "value_sql": "NULL",
2800
+ "expect": { "warehouse": null }
2801
+ },
2802
+ {
2803
+ "key": "duckdb/UINTEGER/plain",
2804
+ "native_type": "UINTEGER",
2805
+ "class": "plain",
2806
+ "value_sql": "42",
2807
+ "expect": { "warehouse": 42 }
2808
+ },
2809
+ {
2810
+ "key": "duckdb/UINTEGER/zero",
2811
+ "native_type": "UINTEGER",
2812
+ "class": "zero",
2813
+ "value_sql": "0",
2814
+ "expect": { "warehouse": 0 }
2815
+ },
2816
+ {
2817
+ "key": "duckdb/UINTEGER/null",
2818
+ "native_type": "UINTEGER",
2819
+ "class": "null",
2820
+ "value_sql": "NULL",
2821
+ "expect": { "warehouse": null }
2822
+ },
2823
+ {
2824
+ "key": "duckdb/UBIGINT/plain",
2825
+ "native_type": "UBIGINT",
2826
+ "class": "plain",
2827
+ "value_sql": "42",
2828
+ "expect": { "warehouse": 42 }
2829
+ },
2830
+ {
2831
+ "key": "duckdb/UBIGINT/zero",
2832
+ "native_type": "UBIGINT",
2833
+ "class": "zero",
2834
+ "value_sql": "0",
2835
+ "expect": { "warehouse": 0 }
2836
+ },
2837
+ {
2838
+ "key": "duckdb/UBIGINT/precision_gt_18",
2839
+ "native_type": "UBIGINT",
2840
+ "class": "precision_gt_18",
2841
+ "value_sql": "'18446744073709551615'::UBIGINT",
2842
+ "expect": { "warehouse": "18446744073709551615" }
2843
+ },
2844
+ {
2845
+ "key": "duckdb/UBIGINT/null",
2846
+ "native_type": "UBIGINT",
2847
+ "class": "null",
2848
+ "value_sql": "NULL",
2849
+ "expect": { "warehouse": null }
2850
+ },
2851
+ {
2852
+ "key": "duckdb/HUGEINT/plain",
2853
+ "native_type": "HUGEINT",
2854
+ "class": "plain",
2855
+ "value_sql": "42",
2856
+ "expect": { "warehouse": "42" }
2857
+ },
2858
+ {
2859
+ "key": "duckdb/HUGEINT/negative",
2860
+ "native_type": "HUGEINT",
2861
+ "class": "negative",
2862
+ "value_sql": "-42",
2863
+ "expect": { "warehouse": "-42" }
2864
+ },
2865
+ {
2866
+ "key": "duckdb/HUGEINT/zero",
2867
+ "native_type": "HUGEINT",
2868
+ "class": "zero",
2869
+ "value_sql": "0",
2870
+ "expect": { "warehouse": "0" }
2871
+ },
2872
+ {
2873
+ "key": "duckdb/HUGEINT/precision_gt_18",
2874
+ "native_type": "HUGEINT",
2875
+ "class": "precision_gt_18",
2876
+ "value_sql": "'12345678901234567890123456789012345678'::HUGEINT",
2877
+ "expect": { "warehouse": "12345678901234567890123456789012345678" }
2878
+ },
2879
+ {
2880
+ "key": "duckdb/HUGEINT/null",
2881
+ "native_type": "HUGEINT",
2882
+ "class": "null",
2883
+ "value_sql": "NULL",
2884
+ "expect": { "warehouse": null }
2885
+ },
2886
+ {
2887
+ "key": "duckdb/UHUGEINT/plain",
2888
+ "native_type": "UHUGEINT",
2889
+ "class": "plain",
2890
+ "value_sql": "42",
2891
+ "expect": { "warehouse": "42" }
2892
+ },
2893
+ {
2894
+ "key": "duckdb/UHUGEINT/zero",
2895
+ "native_type": "UHUGEINT",
2896
+ "class": "zero",
2897
+ "value_sql": "0",
2898
+ "expect": { "warehouse": "0" }
2899
+ },
2900
+ {
2901
+ "key": "duckdb/UHUGEINT/precision_gt_18",
2902
+ "native_type": "UHUGEINT",
2903
+ "class": "precision_gt_18",
2904
+ "value_sql": "'12345678901234567890123456789012345678'::UHUGEINT",
2905
+ "expect": { "warehouse": "12345678901234567890123456789012345678" }
2906
+ },
2907
+ {
2908
+ "key": "duckdb/UHUGEINT/null",
2909
+ "native_type": "UHUGEINT",
2910
+ "class": "null",
2911
+ "value_sql": "NULL",
2912
+ "expect": { "warehouse": null }
2913
+ },
2914
+ {
2915
+ "key": "duckdb/FLOAT/plain",
2916
+ "native_type": "FLOAT",
2917
+ "class": "plain",
2918
+ "value_sql": "0.1",
2919
+ "expect": { "warehouse": .10000000149011612 }
2920
+ },
2921
+ {
2922
+ "key": "duckdb/FLOAT/negative",
2923
+ "native_type": "FLOAT",
2924
+ "class": "negative",
2925
+ "value_sql": "-1.5",
2926
+ "expect": { "warehouse": -1.5 }
2927
+ },
2928
+ {
2929
+ "key": "duckdb/FLOAT/zero",
2930
+ "native_type": "FLOAT",
2931
+ "class": "zero",
2932
+ "value_sql": "0",
2933
+ "expect": { "warehouse": 0 }
2934
+ },
2935
+ {
2936
+ "key": "duckdb/FLOAT/nan_inf",
2937
+ "native_type": "FLOAT",
2938
+ "class": "nan_inf",
2939
+ "value_sql": "'nan'::FLOAT",
2940
+ "expect": { "warehouse": null }
2941
+ },
2942
+ {
2943
+ "key": "duckdb/FLOAT/null",
2944
+ "native_type": "FLOAT",
2945
+ "class": "null",
2946
+ "value_sql": "NULL",
2947
+ "expect": { "warehouse": null }
2948
+ },
2949
+ {
2950
+ "key": "duckdb/REAL/plain",
2951
+ "native_type": "REAL",
2952
+ "class": "plain",
2953
+ "value_sql": "0.1",
2954
+ "expect": { "warehouse": .10000000149011612 }
2955
+ },
2956
+ {
2957
+ "key": "duckdb/FLOAT4/plain",
2958
+ "native_type": "FLOAT4",
2959
+ "class": "plain",
2960
+ "value_sql": "0.1",
2961
+ "expect": { "warehouse": .10000000149011612 }
2962
+ },
2963
+ {
2964
+ "key": "duckdb/DOUBLE/plain",
2965
+ "native_type": "DOUBLE",
2966
+ "class": "plain",
2967
+ "value_sql": "0.1",
2968
+ "expect": { "warehouse": .1 }
2969
+ },
2970
+ {
2971
+ "key": "duckdb/DOUBLE/negative",
2972
+ "native_type": "DOUBLE",
2973
+ "class": "negative",
2974
+ "value_sql": "-1.5",
2975
+ "expect": { "warehouse": -1.5 }
2976
+ },
2977
+ {
2978
+ "key": "duckdb/DOUBLE/zero",
2979
+ "native_type": "DOUBLE",
2980
+ "class": "zero",
2981
+ "value_sql": "0",
2982
+ "expect": { "warehouse": 0 }
2983
+ },
2984
+ {
2985
+ "key": "duckdb/DOUBLE/nan_inf",
2986
+ "native_type": "DOUBLE",
2987
+ "class": "nan_inf",
2988
+ "value_sql": "'inf'::DOUBLE",
2989
+ "expect": { "warehouse": null }
2990
+ },
2991
+ {
2992
+ "key": "duckdb/DOUBLE/null",
2993
+ "native_type": "DOUBLE",
2994
+ "class": "null",
2995
+ "value_sql": "NULL",
2996
+ "expect": { "warehouse": null }
2997
+ },
2998
+ {
2999
+ "key": "duckdb/FLOAT8/plain",
3000
+ "native_type": "FLOAT8",
3001
+ "class": "plain",
3002
+ "value_sql": "0.1",
3003
+ "expect": { "warehouse": .1 }
3004
+ },
3005
+ {
3006
+ "key": "duckdb/DECIMAL(18,4)/plain",
3007
+ "native_type": "DECIMAL(18,4)",
3008
+ "class": "plain",
3009
+ "value_sql": "1234.5678",
3010
+ "expect": { "warehouse": "1234.5678" }
3011
+ },
3012
+ {
3013
+ "key": "duckdb/DECIMAL(18,4)/negative",
3014
+ "native_type": "DECIMAL(18,4)",
3015
+ "class": "negative",
3016
+ "value_sql": "-1.25",
3017
+ "expect": { "warehouse": "-1.2500" }
3018
+ },
3019
+ {
3020
+ "key": "duckdb/DECIMAL(18,4)/zero",
3021
+ "native_type": "DECIMAL(18,4)",
3022
+ "class": "zero",
3023
+ "value_sql": "0",
3024
+ "expect": { "warehouse": "0.0000" }
3025
+ },
3026
+ {
3027
+ "key": "duckdb/DECIMAL(18,4)/null",
3028
+ "native_type": "DECIMAL(18,4)",
3029
+ "class": "null",
3030
+ "value_sql": "NULL",
3031
+ "expect": { "warehouse": null }
3032
+ },
3033
+ {
3034
+ "key": "duckdb/DECIMAL(38,10)/precision_gt_18",
3035
+ "native_type": "DECIMAL(38,10)",
3036
+ "class": "precision_gt_18",
3037
+ "value_sql": "'1234567890123456789.0123456789'::DECIMAL(38,10)",
3038
+ "expect": { "warehouse": "1234567890123456789.0123456789" }
3039
+ },
3040
+ {
3041
+ "key": "duckdb/VARCHAR/plain",
3042
+ "native_type": "VARCHAR",
3043
+ "class": "plain",
3044
+ "value_sql": "'plain text'",
3045
+ "expect": { "warehouse": "plain text" }
3046
+ },
3047
+ {
3048
+ "key": "duckdb/VARCHAR/empty",
3049
+ "native_type": "VARCHAR",
3050
+ "class": "empty",
3051
+ "value_sql": "''",
3052
+ "expect": { "warehouse": "" }
3053
+ },
3054
+ {
3055
+ "key": "duckdb/VARCHAR/whitespace",
3056
+ "native_type": "VARCHAR",
3057
+ "class": "whitespace",
3058
+ "value_sql": "chr(32) || chr(9) || chr(10) || chr(32)",
3059
+ "expect": { "warehouse": " \n " }
3060
+ },
3061
+ {
3062
+ "key": "duckdb/VARCHAR/non_bmp",
3063
+ "native_type": "VARCHAR",
3064
+ "class": "non_bmp",
3065
+ "value_sql": "'𝔘nicode'",
3066
+ "expect": { "warehouse": "𝔘nicode" }
3067
+ },
3068
+ {
3069
+ "key": "duckdb/VARCHAR/len_gt_1k",
3070
+ "native_type": "VARCHAR",
3071
+ "class": "len_gt_1k",
3072
+ "value_sql": "repeat('0123456789', 101)",
3073
+ "expect": { "warehouse": "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" }
3074
+ },
3075
+ {
3076
+ "key": "duckdb/VARCHAR/null",
3077
+ "native_type": "VARCHAR",
3078
+ "class": "null",
3079
+ "value_sql": "NULL",
3080
+ "expect": { "warehouse": null }
3081
+ },
3082
+ {
3083
+ "key": "duckdb/CHAR/plain",
3084
+ "native_type": "CHAR",
3085
+ "class": "plain",
3086
+ "value_sql": "'plain text'",
3087
+ "expect": { "warehouse": "plain text" }
3088
+ },
3089
+ {
3090
+ "key": "duckdb/BPCHAR/plain",
3091
+ "native_type": "BPCHAR",
3092
+ "class": "plain",
3093
+ "value_sql": "'plain text'",
3094
+ "expect": { "warehouse": "plain text" }
3095
+ },
3096
+ {
3097
+ "key": "duckdb/TEXT/plain",
3098
+ "native_type": "TEXT",
3099
+ "class": "plain",
3100
+ "value_sql": "'plain text'",
3101
+ "expect": { "warehouse": "plain text" }
3102
+ },
3103
+ {
3104
+ "key": "duckdb/STRING/plain",
3105
+ "native_type": "STRING",
3106
+ "class": "plain",
3107
+ "value_sql": "'plain text'",
3108
+ "expect": { "warehouse": "plain text" }
3109
+ },
3110
+ {
3111
+ "key": "duckdb/UUID/plain",
3112
+ "native_type": "UUID",
3113
+ "class": "plain",
3114
+ "value_sql": "'00000000-0000-4000-8000-000000000001'",
3115
+ "expect": { "warehouse": "00000000-0000-4000-8000-000000000001" }
3116
+ },
3117
+ {
3118
+ "key": "duckdb/UUID/null",
3119
+ "native_type": "UUID",
3120
+ "class": "null",
3121
+ "value_sql": "NULL",
3122
+ "expect": { "warehouse": null }
3123
+ },
3124
+ {
3125
+ "key": "duckdb/BLOB/plain",
3126
+ "native_type": "BLOB",
3127
+ "class": "plain",
3128
+ "value_sql": "'\\x00\\x01\\xFF'::BLOB",
3129
+ "expect": { "warehouse": "<3 bytes>" }
3130
+ },
3131
+ {
3132
+ "key": "duckdb/BLOB/empty",
3133
+ "native_type": "BLOB",
3134
+ "class": "empty",
3135
+ "value_sql": "''::BLOB",
3136
+ "expect": { "warehouse": "<0 bytes>" }
3137
+ },
3138
+ {
3139
+ "key": "duckdb/BLOB/null",
3140
+ "native_type": "BLOB",
3141
+ "class": "null",
3142
+ "value_sql": "NULL",
3143
+ "expect": { "warehouse": null }
3144
+ },
3145
+ {
3146
+ "key": "duckdb/BYTEA/plain",
3147
+ "native_type": "BYTEA",
3148
+ "class": "plain",
3149
+ "value_sql": "'\\x00\\x01\\xFF'::BLOB",
3150
+ "expect": { "warehouse": "<3 bytes>" }
3151
+ },
3152
+ {
3153
+ "key": "duckdb/BINARY/plain",
3154
+ "native_type": "BINARY",
3155
+ "class": "plain",
3156
+ "value_sql": "'\\x00\\x01\\xFF'::BLOB",
3157
+ "expect": { "warehouse": "<3 bytes>" }
3158
+ },
3159
+ {
3160
+ "key": "duckdb/VARBINARY/plain",
3161
+ "native_type": "VARBINARY",
3162
+ "class": "plain",
3163
+ "value_sql": "'\\x00\\x01\\xFF'::BLOB",
3164
+ "expect": { "warehouse": "<3 bytes>" }
3165
+ },
3166
+ {
3167
+ "key": "duckdb/DATE/plain",
3168
+ "native_type": "DATE",
3169
+ "class": "plain",
3170
+ "value_sql": "DATE '2024-03-10'",
3171
+ "expect": { "warehouse": "2024-03-10" }
3172
+ },
3173
+ {
3174
+ "key": "duckdb/DATE/date_before_1970",
3175
+ "native_type": "DATE",
3176
+ "class": "date_before_1970",
3177
+ "value_sql": "DATE '1969-12-31'",
3178
+ "expect": { "warehouse": "1969-12-31" }
3179
+ },
3180
+ {
3181
+ "key": "duckdb/DATE/date_after_2100",
3182
+ "native_type": "DATE",
3183
+ "class": "date_after_2100",
3184
+ "value_sql": "DATE '2150-06-01'",
3185
+ "expect": { "warehouse": "2150-06-01" }
3186
+ },
3187
+ {
3188
+ "key": "duckdb/DATE/null",
3189
+ "native_type": "DATE",
3190
+ "class": "null",
3191
+ "value_sql": "NULL",
3192
+ "expect": { "warehouse": null }
3193
+ },
3194
+ {
3195
+ "key": "duckdb/TIMESTAMP/plain",
3196
+ "native_type": "TIMESTAMP",
3197
+ "class": "plain",
3198
+ "value_sql": "TIMESTAMP '2024-03-10 12:34:56.789'",
3199
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
3200
+ },
3201
+ {
3202
+ "key": "duckdb/TIMESTAMP/date_before_1970",
3203
+ "native_type": "TIMESTAMP",
3204
+ "class": "date_before_1970",
3205
+ "value_sql": "TIMESTAMP '1969-07-20 20:17:40.5'",
3206
+ "expect": { "warehouse": "1969-07-20 20:17:40.500000" }
3207
+ },
3208
+ {
3209
+ "key": "duckdb/TIMESTAMP/date_after_2100",
3210
+ "native_type": "TIMESTAMP",
3211
+ "class": "date_after_2100",
3212
+ "value_sql": "TIMESTAMP '2150-01-01 00:00:00'",
3213
+ "expect": { "warehouse": "2150-01-01 00:00:00" }
3214
+ },
3215
+ {
3216
+ "key": "duckdb/TIMESTAMP/null",
3217
+ "native_type": "TIMESTAMP",
3218
+ "class": "null",
3219
+ "value_sql": "NULL",
3220
+ "expect": { "warehouse": null }
3221
+ },
3222
+ {
3223
+ "key": "duckdb/DATETIME/plain",
3224
+ "native_type": "DATETIME",
3225
+ "class": "plain",
3226
+ "value_sql": "TIMESTAMP '2024-03-10 12:34:56.789'",
3227
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
3228
+ },
3229
+ {
3230
+ "key": "duckdb/TIMESTAMP_US/plain",
3231
+ "native_type": "TIMESTAMP_US",
3232
+ "class": "plain",
3233
+ "value_sql": "TIMESTAMP '2024-03-10 12:34:56.789'",
3234
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
3235
+ },
3236
+ {
3237
+ "key": "duckdb/TIMESTAMP_S/plain",
3238
+ "native_type": "TIMESTAMP_S",
3239
+ "class": "plain",
3240
+ "value_sql": "'2024-03-10 12:34:56'::TIMESTAMP_S",
3241
+ "expect": { "warehouse": "2024-03-10 12:34:56" }
3242
+ },
3243
+ {
3244
+ "key": "duckdb/TIMESTAMP_S/date_before_1970",
3245
+ "native_type": "TIMESTAMP_S",
3246
+ "class": "date_before_1970",
3247
+ "value_sql": "'1969-07-20 20:17:40'::TIMESTAMP_S",
3248
+ "expect": { "warehouse": "1969-07-20 20:17:40" }
3249
+ },
3250
+ {
3251
+ "key": "duckdb/TIMESTAMP_S/date_after_2100",
3252
+ "native_type": "TIMESTAMP_S",
3253
+ "class": "date_after_2100",
3254
+ "value_sql": "'2150-01-01 00:00:00'::TIMESTAMP_S",
3255
+ "expect": { "warehouse": "2150-01-01 00:00:00" }
3256
+ },
3257
+ {
3258
+ "key": "duckdb/TIMESTAMP_S/null",
3259
+ "native_type": "TIMESTAMP_S",
3260
+ "class": "null",
3261
+ "value_sql": "NULL",
3262
+ "expect": { "warehouse": null }
3263
+ },
3264
+ {
3265
+ "key": "duckdb/TIMESTAMP_MS/plain",
3266
+ "native_type": "TIMESTAMP_MS",
3267
+ "class": "plain",
3268
+ "value_sql": "'2024-03-10 12:34:56.789'::TIMESTAMP_MS",
3269
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
3270
+ },
3271
+ {
3272
+ "key": "duckdb/TIMESTAMP_MS/date_before_1970",
3273
+ "native_type": "TIMESTAMP_MS",
3274
+ "class": "date_before_1970",
3275
+ "value_sql": "'1969-07-20 20:17:40.5'::TIMESTAMP_MS",
3276
+ "expect": { "warehouse": "1969-07-20 20:17:40.500000" }
3277
+ },
3278
+ {
3279
+ "key": "duckdb/TIMESTAMP_MS/date_after_2100",
3280
+ "native_type": "TIMESTAMP_MS",
3281
+ "class": "date_after_2100",
3282
+ "value_sql": "'2150-01-01 00:00:00'::TIMESTAMP_MS",
3283
+ "expect": { "warehouse": "2150-01-01 00:00:00" }
3284
+ },
3285
+ {
3286
+ "key": "duckdb/TIMESTAMP_MS/null",
3287
+ "native_type": "TIMESTAMP_MS",
3288
+ "class": "null",
3289
+ "value_sql": "NULL",
3290
+ "expect": { "warehouse": null }
3291
+ },
3292
+ {
3293
+ "key": "duckdb/TIMESTAMP_NS/plain",
3294
+ "native_type": "TIMESTAMP_NS",
3295
+ "class": "plain",
3296
+ "value_sql": "'2024-03-10 12:34:56.789123456'::TIMESTAMP_NS",
3297
+ "expect": { "warehouse": "2024-03-10 12:34:56.789123" }
3298
+ },
3299
+ {
3300
+ "key": "duckdb/TIMESTAMP_NS/date_before_1970",
3301
+ "native_type": "TIMESTAMP_NS",
3302
+ "class": "date_before_1970",
3303
+ "value_sql": "'1969-07-20 20:17:40.500000001'::TIMESTAMP_NS",
3304
+ "expect": { "warehouse": "1969-07-20 20:17:40.500000" }
3305
+ },
3306
+ {
3307
+ "key": "duckdb/TIMESTAMP_NS/date_after_2100",
3308
+ "native_type": "TIMESTAMP_NS",
3309
+ "class": "date_after_2100",
3310
+ "value_sql": "'2150-01-01 00:00:00'::TIMESTAMP_NS",
3311
+ "expect": { "warehouse": "2150-01-01 00:00:00" }
3312
+ },
3313
+ {
3314
+ "key": "duckdb/TIMESTAMP_NS/null",
3315
+ "native_type": "TIMESTAMP_NS",
3316
+ "class": "null",
3317
+ "value_sql": "NULL",
3318
+ "expect": { "warehouse": null }
3319
+ },
3320
+ {
3321
+ "key": "duckdb/TIMESTAMP WITH TIME ZONE/plain",
3322
+ "native_type": "TIMESTAMP WITH TIME ZONE",
3323
+ "class": "plain",
3324
+ "value_sql": "TIMESTAMPTZ '2024-03-10 12:34:56.789+00'",
3325
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
3326
+ },
3327
+ {
3328
+ "key": "duckdb/TIMESTAMP WITH TIME ZONE/tz_bearing",
3329
+ "native_type": "TIMESTAMP WITH TIME ZONE",
3330
+ "class": "tz_bearing",
3331
+ "value_sql": "TIMESTAMPTZ '2024-03-10 12:34:56+05:30'",
3332
+ "expect": { "warehouse": "2024-03-10 07:04:56" }
3333
+ },
3334
+ {
3335
+ "key": "duckdb/TIMESTAMP WITH TIME ZONE/date_before_1970",
3336
+ "native_type": "TIMESTAMP WITH TIME ZONE",
3337
+ "class": "date_before_1970",
3338
+ "value_sql": "TIMESTAMPTZ '1969-07-20 20:17:40.5+00'",
3339
+ "expect": { "warehouse": "1969-07-20 20:17:40.500000" }
3340
+ },
3341
+ {
3342
+ "key": "duckdb/TIMESTAMP WITH TIME ZONE/date_after_2100",
3343
+ "native_type": "TIMESTAMP WITH TIME ZONE",
3344
+ "class": "date_after_2100",
3345
+ "value_sql": "TIMESTAMPTZ '2150-01-01 00:00:00+00'",
3346
+ "expect": { "warehouse": "2150-01-01 00:00:00" }
3347
+ },
3348
+ {
3349
+ "key": "duckdb/TIMESTAMP WITH TIME ZONE/null",
3350
+ "native_type": "TIMESTAMP WITH TIME ZONE",
3351
+ "class": "null",
3352
+ "value_sql": "NULL",
3353
+ "expect": { "warehouse": null }
3354
+ },
3355
+ {
3356
+ "key": "duckdb/TIMESTAMPTZ/plain",
3357
+ "native_type": "TIMESTAMPTZ",
3358
+ "class": "plain",
3359
+ "value_sql": "TIMESTAMPTZ '2024-03-10 12:34:56.789+00'",
3360
+ "expect": { "warehouse": "2024-03-10 12:34:56.789000" }
3361
+ },
3362
+ {
3363
+ "key": "duckdb/JSON/nested_json",
3364
+ "native_type": "JSON",
3365
+ "class": "nested_json",
3366
+ "value_sql": "'{\"a\":{\"b\":[1,2]},\"s\":\"x\"}'",
3367
+ "expect": { "warehouse": "{\"a\":{\"b\":[1,2]},\"s\":\"x\"}" }
3368
+ },
3369
+ {
3370
+ "key": "duckdb/JSON/array",
3371
+ "native_type": "JSON",
3372
+ "class": "array",
3373
+ "value_sql": "'[1,\"two\",null]'",
3374
+ "expect": { "warehouse": "[1,\"two\",null]" }
3375
+ },
3376
+ {
3377
+ "key": "duckdb/JSON/null",
3378
+ "native_type": "JSON",
3379
+ "class": "null",
3380
+ "value_sql": "NULL",
3381
+ "expect": { "warehouse": null }
3382
+ },
3383
+ {
3384
+ "key": "duckdb/INTEGER[]/array",
3385
+ "native_type": "INTEGER[]",
3386
+ "class": "array",
3387
+ "value_sql": "[1, -2, 3]",
3388
+ "expect": { "warehouse": "List([Int(1), Int(-2), Int(3)])" }
3389
+ },
3390
+ {
3391
+ "key": "duckdb/INTEGER[]/empty",
3392
+ "native_type": "INTEGER[]",
3393
+ "class": "empty",
3394
+ "value_sql": "[]",
3395
+ "expect": { "warehouse": "List([])" }
3396
+ },
3397
+ {
3398
+ "key": "duckdb/INTEGER[]/null",
3399
+ "native_type": "INTEGER[]",
3400
+ "class": "null",
3401
+ "value_sql": "NULL",
3402
+ "expect": { "warehouse": null }
3403
+ }
3404
+ ] }
3405
+ }
3406
+ };
3407
+
3408
+ //#endregion
3409
+ //#region src/testing/shape-zoo-sha256.ts
3410
+ const ZOO_SHA256 = "04f75f9054a46e521d8787d65f5d214440d041860971c77e66edc7bfbaf8d16a";
3411
+
3412
+ //#endregion
3413
+ //#region src/testing/zoo.ts
3414
+ /** A value a read would REFUSE rather than return: `expect.oltp.$error`. */
3415
+ var ZooRefusal = class {
3416
+ constructor(column, nativeType, detail) {
3417
+ this.column = column;
3418
+ this.nativeType = nativeType;
3419
+ this.detail = detail;
3420
+ }
3421
+ /** The host's full sentence for it, from the contract. */
3422
+ message() {
3423
+ return render(REFUSALS.oltpUnsupportedColumn, {
3424
+ name: this.column,
3425
+ ty: this.nativeType
3426
+ });
3427
+ }
3428
+ };
3429
+ const ZOO = shape_zoo_default;
3430
+ /** The zoo table's name, from the fixture's digest — the canary's `zooTableName`. */
3431
+ function zooTableName(sha256Hex = ZOO_SHA256) {
3432
+ return `oxy_shape_zoo_${sha256Hex.slice(0, 8)}`;
3433
+ }
3434
+ /** `c001`, `c002`, … — the zoo column for case `index`. */
3435
+ function zooColumn(index) {
3436
+ return `c${String(index + 1).padStart(3, "0")}`;
3437
+ }
3438
+ const isError = (v) => typeof v === "object" && v !== null && "$error" in v;
3439
+ /** What a read of case `c` on `plane` returns — or refuses. */
3440
+ function expectation(c, plane, column) {
3441
+ const value = plane === "oltp" ? c.expect.oltp : c.expect.warehouse;
3442
+ return isError(value) ? new ZooRefusal(column, c.native_type, value.$error) : value;
3443
+ }
3444
+ /** Every case of `engine` for `nativeType`, as written in the zoo. */
3445
+ function casesFor(engine, nativeType) {
3446
+ return ZOO.engines[engine].cases.filter((c) => c.native_type === nativeType);
3447
+ }
3448
+ /** The native types the zoo pins for `engine`, for a declaration error to list. */
3449
+ function knownTypes(engine) {
3450
+ return [...new Set(ZOO.engines[engine].cases.map((c) => c.native_type))];
3451
+ }
3452
+ const I64_MAX = 9223372036854775807n;
3453
+ const I64_MIN = -9223372036854775808n;
3454
+ /**
3455
+ * Render one SQL-side value of a typed column through the zoo.
3456
+ *
3457
+ * - The value IS a case's `value_sql` for this type → that case's expectation
3458
+ * (`source: "zoo"`).
3459
+ * - `NULL` → `null`.
3460
+ * - Otherwise the `plain` case's SHAPE decides: a number-shaped type parses the
3461
+ * literal, except that an integer outside `i64` becomes its exact digits as a
3462
+ * string where the zoo pins that (`precision_gt_18` expecting a string) — the
3463
+ * host reads an overflowing column as `u64` rendered to text; a string-shaped
3464
+ * type unquotes; a boolean-shaped type reads `true`/`false`/`1`/`0`; a JSON
3465
+ * shape parses (`source: "typed"`).
3466
+ */
3467
+ function renderValue(engine, nativeType, valueSql, plane, column) {
3468
+ const cases = casesFor(engine, nativeType);
3469
+ const raw = valueSql.trim();
3470
+ const exact = cases.find((c) => c.value_sql.trim() === raw);
3471
+ if (exact) return {
3472
+ value: expectation(exact, plane, column),
3473
+ source: "zoo"
3474
+ };
3475
+ if (/^NULL$/i.test(raw)) return {
3476
+ value: null,
3477
+ source: "typed"
3478
+ };
3479
+ const shape = expectation(cases.find((c) => c.class === "plain") ?? cases[0], plane, column);
3480
+ if (shape instanceof ZooRefusal) return {
3481
+ value: shape,
3482
+ source: "zoo"
3483
+ };
3484
+ return {
3485
+ value: shaped(raw, shape, cases, plane, column),
3486
+ source: "typed"
3487
+ };
3488
+ }
3489
+ function shaped(raw, shape, cases, plane, column) {
3490
+ const unquoted = raw.startsWith("'") && raw.endsWith("'") ? raw.slice(1, -1).replace(/''/g, "'") : raw;
3491
+ switch (typeof shape) {
3492
+ case "number": {
3493
+ if (/^-?\d+$/.test(raw)) {
3494
+ const big = BigInt(raw);
3495
+ if (big > I64_MAX || big < I64_MIN) {
3496
+ const wide = cases.find((c) => c.class === "precision_gt_18");
3497
+ if (wide && typeof expectation(wide, plane, column) === "string") return raw;
3498
+ }
3499
+ }
3500
+ const n = Number(unquoted);
3501
+ return Number.isNaN(n) ? unquoted : n;
3502
+ }
3503
+ case "boolean": return /^(true|1)$/i.test(unquoted);
3504
+ case "string": return unquoted;
3505
+ case "object":
3506
+ if (shape === null) return null;
3507
+ try {
3508
+ return JSON.parse(unquoted);
3509
+ } catch {
3510
+ return unquoted;
3511
+ }
3512
+ default: return unquoted;
3513
+ }
3514
+ }
3515
+
3516
+ //#endregion
3517
+ //#region src/testing/stores.ts
3518
+ const RANK = {
3519
+ zoo: 0,
3520
+ typed: 1,
3521
+ author: 2
3522
+ };
3523
+ const weakest = (a, b) => a === null || RANK[b] > RANK[a] ? b : a;
3524
+ /**
3525
+ * One SQL-evaluating store: a warehouse database, the OLTP schema or the
3526
+ * Airhouse schema. `engine` picks which zoo cases render typed columns;
3527
+ * `plane` picks which expectation a case yields.
3528
+ */
3529
+ var TableStore = class {
3530
+ constructor(engine, plane, schema = null) {
3531
+ this.engine = engine;
3532
+ this.plane = plane;
3533
+ this.schema = schema;
3534
+ this.tables = /* @__PURE__ */ new Map();
3535
+ }
3536
+ /** The zoo table for this engine: column `cNNN` is case NNN's expectation. */
3537
+ zoo() {
3538
+ const cases = ZOO.engines[this.engine].cases;
3539
+ const columns = {};
3540
+ const values = {};
3541
+ cases.forEach((c, i) => {
3542
+ const column = zooColumn(i);
3543
+ columns[column] = c.native_type;
3544
+ values[column] = expectation(c, this.plane, column);
3545
+ });
3546
+ this.tables.set(zooTableName(), {
3547
+ name: zooTableName(),
3548
+ columns,
3549
+ rows: [{
3550
+ values,
3551
+ source: "zoo"
3552
+ }]
3553
+ });
3554
+ return this;
3555
+ }
3556
+ /**
3557
+ * Declare a typed table: `{ id: "UInt64", amount: "Decimal(18, 4)" }`. A
3558
+ * type the zoo has no case for is an error here, not a guess at read time.
3559
+ */
3560
+ table(name, columns) {
3561
+ const key = this.key(name);
3562
+ for (const [column, type] of Object.entries(columns)) if (!ZOO.engines[this.engine].cases.some((c) => c.native_type === type)) throw contextError(`the zoo has no ${this.engine} case for type "${type}" (column "${column}" of "${name}"); it pins: ${knownTypes(this.engine).join(", ")}`);
3563
+ if (!this.tables.has(key)) this.tables.set(key, {
3564
+ name: key,
3565
+ columns,
3566
+ rows: []
3567
+ });
3568
+ return new TypedTable(this, key);
3569
+ }
3570
+ /** Seed rows as JS values, unrendered — every read of them is `source: "author"`. */
3571
+ raw(name, rows) {
3572
+ const key = this.key(name);
3573
+ const table = this.tables.get(key) ?? {
3574
+ name: key,
3575
+ columns: null,
3576
+ rows: []
3577
+ };
3578
+ for (const row of rows) table.rows.push({
3579
+ values: { ...row },
3580
+ source: "author"
3581
+ });
3582
+ this.tables.set(key, table);
3583
+ return this;
3584
+ }
3585
+ /** Every row of `name` as a function would read it; a `$error` cell is its refusal text. */
3586
+ rows(name) {
3587
+ return this.lookup(name)?.rows.map((r) => materialise(r.values)) ?? [];
3588
+ }
3589
+ /** The names of every table declared, seeded or created. */
3590
+ tableNames() {
3591
+ return [...this.tables.keys()];
3592
+ }
3593
+ /** Whether `name` exists. */
3594
+ has(name) {
3595
+ return this.lookup(name) !== void 0;
3596
+ }
3597
+ /** Evaluate `sql` as a read: rows, or a throw. */
3598
+ query(sql, params = []) {
3599
+ const statement = parse(sql);
3600
+ if (statement.kind !== "select") throw contextError(`expected a SELECT, got ${statement.kind.toUpperCase()}: ${sql.slice(0, 80)}`);
3601
+ return this.select(statement, params);
3602
+ }
3603
+ /** Evaluate `sql` as a statement: rows affected, or a throw. */
3604
+ exec(sql, params = []) {
3605
+ const statement = parse(sql);
3606
+ switch (statement.kind) {
3607
+ case "create": return this.create(statement);
3608
+ case "insert": return this.insert(statement, params);
3609
+ case "delete": return this.remove(statement, params);
3610
+ case "update": return this.update(statement, params);
3611
+ case "select": return this.select(statement, params).rows.length;
3612
+ }
3613
+ }
3614
+ /** Append JS rows to `name` (`ctx.warehouse.insert`, `ctx.airhouse.append`): unrendered. */
3615
+ append(name, rows) {
3616
+ this.raw(name, rows);
3617
+ return rows.length;
3618
+ }
3619
+ /** Snapshot every table, for `ctx.tx` rollback. */
3620
+ snapshot() {
3621
+ const copy = new Map([...this.tables].map(([k, t]) => [k, {
3622
+ ...t,
3623
+ rows: t.rows.map((r) => ({
3624
+ ...r,
3625
+ values: { ...r.values }
3626
+ }))
3627
+ }]));
3628
+ return () => {
3629
+ this.tables.clear();
3630
+ for (const [k, t] of copy) this.tables.set(k, t);
3631
+ };
3632
+ }
3633
+ key(name) {
3634
+ return this.schema && name.startsWith(`${this.schema}.`) ? name.slice(this.schema.length + 1) : name;
3635
+ }
3636
+ lookup(name) {
3637
+ return this.tables.get(this.key(name)) ?? this.tables.get(name);
3638
+ }
3639
+ require(name, statement) {
3640
+ const table = this.lookup(name);
3641
+ if (!table) throw contextError(`${statement.kind.toUpperCase()} names a table the test context does not have: "${name}". Declare it with t.state.<store>.table(name, columns), seed it with .raw(name, rows), or let the function CREATE it first. Known: ${this.tableNames().join(", ") || "none"}`);
3642
+ return table;
3643
+ }
3644
+ create(statement) {
3645
+ const key = this.key(statement.table);
3646
+ if (this.tables.has(key)) {
3647
+ if (statement.ifNotExists) return 0;
3648
+ throw contextError(`CREATE TABLE "${statement.table}": the table already exists`);
3649
+ }
3650
+ const columns = {};
3651
+ for (const c of statement.columns) columns[c.name] = c.type;
3652
+ this.tables.set(key, {
3653
+ name: key,
3654
+ columns,
3655
+ rows: []
3656
+ });
3657
+ return 0;
3658
+ }
3659
+ insert(statement, params) {
3660
+ const table = this.require(statement.table, statement);
3661
+ const names = statement.columns ?? (table.columns ? Object.keys(table.columns) : null);
3662
+ for (const tuple of statement.tuples) {
3663
+ if (!names || names.length !== tuple.length) throw contextError(`INSERT INTO "${statement.table}" gives ${tuple.length} value(s) for ${names?.length ?? "an unknown number of"} column(s)`);
3664
+ const values = {};
3665
+ let source = null;
3666
+ names.forEach((column, i) => {
3667
+ const type = table.columns?.[column];
3668
+ if (type && !/^\$\d+$/.test(tuple[i].trim())) {
3669
+ const rendered = renderValue(this.engine, type, tuple[i], this.plane, column);
3670
+ values[column] = rendered.value;
3671
+ source = weakest(source, rendered.source);
3672
+ } else {
3673
+ values[column] = literal(tuple[i], params);
3674
+ source = weakest(source, "author");
3675
+ }
3676
+ });
3677
+ table.rows.push({
3678
+ values,
3679
+ source: source ?? "author"
3680
+ });
3681
+ }
3682
+ return statement.tuples.length;
3683
+ }
3684
+ matching(table, statement, params) {
3685
+ return table.rows.filter((row) => statement.where.every((p) => {
3686
+ const cell = row.values[p.column];
3687
+ return p.values.some((v) => looselyEqual(cell, literal(v, params)));
3688
+ }));
3689
+ }
3690
+ select(statement, params) {
3691
+ if (statement.table === null) {
3692
+ const row = {};
3693
+ for (const item of statement.items) if (item.kind === "literal") row[item.alias] = literal(item.raw, params);
3694
+ else throw contextError(`SELECT without FROM can only project literals: ${JSON.stringify(item)}`);
3695
+ return {
3696
+ rows: [row],
3697
+ source: "author"
3698
+ };
3699
+ }
3700
+ const table = this.require(statement.table, statement);
3701
+ let matched = this.matching(table, statement, params);
3702
+ if (statement.items.some((i) => i.kind === "count")) return {
3703
+ rows: [{ [statement.items.find((i) => i.kind === "count")?.alias ?? "count(*)"]: matched.length }],
3704
+ source: matched[0]?.source ?? null
3705
+ };
3706
+ if (statement.orderBy) {
3707
+ const { column, desc } = statement.orderBy;
3708
+ matched = [...matched].sort((a, b) => compare(a.values[column], b.values[column]) * (desc ? -1 : 1));
3709
+ }
3710
+ if (statement.limit !== null) matched = matched.slice(0, statement.limit);
3711
+ let source = null;
3712
+ return {
3713
+ rows: matched.map((stored) => {
3714
+ source = weakest(source, stored.source);
3715
+ const out = {};
3716
+ for (const item of statement.items) if (item.kind === "all") Object.assign(out, materialise(stored.values));
3717
+ else if (item.kind === "column") out[item.alias] = materialise({ v: stored.values[item.column] }).v;
3718
+ else if (item.kind === "literal") out[item.alias] = literal(item.raw, params);
3719
+ return out;
3720
+ }),
3721
+ source
3722
+ };
3723
+ }
3724
+ remove(statement, params) {
3725
+ const table = this.require(statement.table, statement);
3726
+ const gone = new Set(this.matching(table, statement, params));
3727
+ table.rows = table.rows.filter((r) => !gone.has(r));
3728
+ return gone.size;
3729
+ }
3730
+ update(statement, params) {
3731
+ const table = this.require(statement.table, statement);
3732
+ const hit = this.matching(table, statement, params);
3733
+ for (const row of hit) for (const { column, raw } of statement.set) {
3734
+ row.values[column] = literal(raw, params);
3735
+ row.source = "author";
3736
+ }
3737
+ return hit.length;
3738
+ }
3739
+ };
3740
+ /** A declared typed table: insert SQL-side values, rendered through the zoo. */
3741
+ var TypedTable = class {
3742
+ constructor(store, name) {
3743
+ this.store = store;
3744
+ this.name = name;
3745
+ }
3746
+ /** Insert rows of SQL-side values (`{ id: "42", at: "'2024-03-10 12:34:56'" }`). */
3747
+ insert(rows) {
3748
+ for (const row of rows) {
3749
+ const columns = Object.keys(row);
3750
+ const values = columns.map((c) => row[c]);
3751
+ this.store.exec(`INSERT INTO ${this.name} (${columns.join(", ")}) VALUES (${values.join(", ")})`);
3752
+ }
3753
+ return this;
3754
+ }
3755
+ };
3756
+ /** A stored row as a read returns it; a refusal cell throws the host's sentence. */
3757
+ function materialise(values) {
3758
+ const out = {};
3759
+ for (const [k, v] of Object.entries(values)) {
3760
+ if (v instanceof ZooRefusal) throw refusalOf(v);
3761
+ out[k] = v;
3762
+ }
3763
+ return out;
3764
+ }
3765
+ /** Marker so the context can wrap a zoo refusal as the OLTP surface's `HostError`. */
3766
+ var ZooRefusalError = class extends Error {
3767
+ constructor(refusal) {
3768
+ super(refusal.message());
3769
+ this.refusal = refusal;
3770
+ this.name = "ZooRefusalError";
3771
+ }
3772
+ };
3773
+ const refusalOf = (r) => new ZooRefusalError(r);
3774
+ function looselyEqual(a, b) {
3775
+ if (a === b) return true;
3776
+ if (a === null || b === null || a === void 0 || b === void 0) return false;
3777
+ return String(a) === String(b);
3778
+ }
3779
+ function compare(a, b) {
3780
+ if (typeof a === "number" && typeof b === "number") return a - b;
3781
+ return String(a).localeCompare(String(b));
3782
+ }
3783
+ /** The `ctx.fetch` side: answers by URL, and what was received. */
3784
+ var FetchStore = class {
3785
+ constructor() {
3786
+ this.received = [];
3787
+ this.answers = [];
3788
+ }
3789
+ /** Answer every URL equal to `match` (or matching the RegExp) with `answer`. */
3790
+ on(match, answer) {
3791
+ this.answers.push({
3792
+ match,
3793
+ answer
3794
+ });
3795
+ return this;
3796
+ }
3797
+ answerFor(url) {
3798
+ return this.answers.find(({ match }) => typeof match === "string" ? match === url : match.test(url))?.answer;
3799
+ }
3800
+ };
3801
+
3802
+ //#endregion
3803
+ //#region src/testing/context.ts
3804
+ const encoder = new TextEncoder();
3805
+ const decoder = new TextDecoder();
3806
+ const nodeBtoa = globalThis.btoa;
3807
+ const nodeAtob = globalThis.atob;
3808
+ const nodeCryptoModule = node_crypto;
3809
+ const DEFAULT_USER = {
3810
+ id: "user-1",
3811
+ email: "author@example.test",
3812
+ orgId: "org-1",
3813
+ name: "Author",
3814
+ appRole: "member",
3815
+ orgRole: "member",
3816
+ teams: [],
3817
+ kind: "user",
3818
+ reach: {
3819
+ everywhere: true,
3820
+ via: "org-member",
3821
+ locations: []
3822
+ }
3823
+ };
3824
+ function createTestContext(manifest, options) {
3825
+ const gates = readGates(manifest, options.function);
3826
+ const manifestSlug = typeof manifest.slug === "string" ? manifest.slug : "";
3827
+ const databases = options.databases ?? {};
3828
+ const calls = [];
3829
+ const overrides = /* @__PURE__ */ new Map();
3830
+ const warehouses = /* @__PURE__ */ new Map();
3831
+ let semanticAnswer = null;
3832
+ const state = {
3833
+ warehouse(database) {
3834
+ const db = databases[database];
3835
+ if (!db) throw contextError(`no database "${database}" in options.databases`);
3836
+ let store = warehouses.get(database);
3837
+ if (!store) {
3838
+ store = new TableStore(db.dialect, "warehouse");
3839
+ warehouses.set(database, store);
3840
+ }
3841
+ return store;
3842
+ },
3843
+ oltp: new TableStore("postgres", "oltp", gates.writerSchema),
3844
+ airhouse: new TableStore("duckdb", "warehouse", gates.writerSchema),
3845
+ storage: /* @__PURE__ */ new Map(),
3846
+ secrets: /* @__PURE__ */ new Map(),
3847
+ emails: [],
3848
+ fetch: new FetchStore(),
3849
+ org: {
3850
+ people: [],
3851
+ places: [],
3852
+ assignments: []
3853
+ },
3854
+ semantic: { on: (answer) => {
3855
+ semanticAnswer = answer;
3856
+ } },
3857
+ airway: { runs: [] }
3858
+ };
3859
+ /** Run one host op: the override or `impl`, recorded either way. */
3860
+ async function op(name, args, impl) {
3861
+ const call = {
3862
+ op: name,
3863
+ args,
3864
+ outcome: "ok"
3865
+ };
3866
+ calls.push(call);
3867
+ try {
3868
+ const result = await (overrides.get(name) ?? impl)(args);
3869
+ if (result && typeof result === "object" && "__source" in result) {
3870
+ const { __source } = result;
3871
+ if (__source) call.source = __source;
3872
+ const rest = Array.isArray(result) ? [...result] : Object.fromEntries(Object.entries(result).filter(([k]) => k !== "__source"));
3873
+ call.result = rest;
3874
+ return rest;
3875
+ }
3876
+ call.result = result;
3877
+ return result;
3878
+ } catch (err) {
3879
+ const thrown = err instanceof ZooRefusalError ? hostError(name.startsWith("tx.") ? SURFACES.tx : SURFACES.oltp, err.message) : err;
3880
+ call.outcome = isHostError(thrown) ? "refused" : "threw";
3881
+ call.message = thrown instanceof Error ? thrown.message : String(thrown);
3882
+ throw thrown;
3883
+ }
3884
+ }
3885
+ /** `check_write_destination` then `destination_write_policy` (`host.rs`, `destinations.rs`). */
3886
+ function checkWriteDestination(surface, database, transaction) {
3887
+ if (!gates.destinations.includes(database)) throw refuse(surface, REFUSALS.destinationNotDeclared, { database });
3888
+ const db = databases[database];
3889
+ if (!db) throw refuse(surface, REFUSALS.databaseNotConfigured, { database });
3890
+ switch (db.kind) {
3891
+ case "airhouse":
3892
+ case "airhouse_managed": return db;
3893
+ case "postgres_managed": throw refuse(surface, REFUSALS.managedOltpWrite, { database });
3894
+ default: {
3895
+ if (gates.customerWarehouseWrites[database]) return db;
3896
+ const words = [REFUSALS.customerWarehouseWrite.refusal];
3897
+ if (transaction) words.push(REFUSALS.customerWarehouseTransaction.refusal);
3898
+ throw hostError(surface, words.join("").replace(/\{database\}/g, database));
3899
+ }
3900
+ }
3901
+ }
3902
+ /**
3903
+ * The host's `WriterCapability` has three states, not two: enabled, disabled,
3904
+ * and enabled-but-the-slug-cannot-back-a-schema. Gating on the boolean alone
3905
+ * let an app whose slug derives no schema pass here and fail closed in
3906
+ * production — the exact shape this module exists to catch.
3907
+ */
3908
+ function requireWriterSchema(surface, store) {
3909
+ if (gates.writerSchema === null) throw refuse(surface, REFUSALS.slugCannotBackASchema, {
3910
+ slug: manifestSlug,
3911
+ store,
3912
+ max: 56
3913
+ });
3914
+ }
3915
+ function requireOltp(surface) {
3916
+ if (!gates.oltp) throw refuse(surface, REFUSALS.oltp);
3917
+ requireWriterSchema(surface, "OLTP");
3918
+ return state.oltp;
3919
+ }
3920
+ function requireAirhouse() {
3921
+ if (!gates.airhouse) throw refuse(SURFACES.airhouse, REFUSALS.airhouse);
3922
+ requireWriterSchema(SURFACES.airhouse, "Airhouse");
3923
+ return state.airhouse;
3924
+ }
3925
+ function requireStorage(opName) {
3926
+ const needsWrite = [
3927
+ "getUploadUrl",
3928
+ "put",
3929
+ "delete",
3930
+ "copy"
3931
+ ].includes(opName);
3932
+ const needsRead = [
3933
+ "getDownloadUrl",
3934
+ "get",
3935
+ "head",
3936
+ "list",
3937
+ "copy"
3938
+ ].includes(opName);
3939
+ if (needsWrite && !gates.storageWrite) throw refuse(SURFACES.storage, REFUSALS.storageWrite);
3940
+ if (needsRead && !gates.storageRead) throw refuse(SURFACES.storage, REFUSALS.storageRead);
3941
+ }
3942
+ function defaultDatabase() {
3943
+ const name = options.defaultDatabase ?? Object.keys(databases)[0];
3944
+ if (!name) throw refuse(SURFACES.query, REFUSALS.noDefaultDatabase);
3945
+ return name;
3946
+ }
3947
+ /** `oltp_statement`: `params` absent or an array, else refused. */
3948
+ function oltpParams(surface, params) {
3949
+ if (params === void 0 || params === null) return [];
3950
+ if (Array.isArray(params)) return params;
3951
+ throw refuse(surface, REFUSALS.oltpParamsNotArray);
3952
+ }
3953
+ const read = (store, sql, params = []) => {
3954
+ const { rows, source } = store.query(sql, params);
3955
+ return {
3956
+ rows,
3957
+ truncated: false,
3958
+ __source: source
3959
+ };
3960
+ };
3961
+ let open = 0;
3962
+ let nextTxId = 0;
3963
+ async function runTx(signature, label, beginOp, beginPayload, fn) {
3964
+ if (typeof fn !== "function") throw new TypeError(REFUSALS.transactionFnNotFunction.refusal.replace("{signature}", signature));
3965
+ let store = null;
3966
+ let incremented = false;
3967
+ const { id } = await op(beginOp, beginPayload, () => {
3968
+ if (beginOp === "tx.begin") {
3969
+ const database = String(beginPayload.database);
3970
+ const db = checkWriteDestination(SURFACES.tx, database, true);
3971
+ if (!DIALECTS[db.dialect].opensTransactions) {
3972
+ const cause = REFUSALS.transactionUnsupported.refusal.replace("{backend}", DIALECTS[db.dialect].name);
3973
+ throw refuse(SURFACES.tx, REFUSALS.transactionOpen, {
3974
+ database,
3975
+ e: cause
3976
+ });
3977
+ }
3978
+ store = state.warehouse(database);
3979
+ } else store = requireOltp(SURFACES.tx);
3980
+ if (open >= 4) throw refuse(SURFACES.tx, REFUSALS.transactionsOpen, { MAX_OPEN: 4 });
3981
+ open++;
3982
+ incremented = true;
3983
+ return { id: ++nextTxId };
3984
+ });
3985
+ const table = store ?? (beginOp === "tx.begin_oltp" ? state.oltp : databases[String(beginPayload.database)] ? state.warehouse(String(beginPayload.database)) : new TableStore("postgres", "warehouse"));
3986
+ const restore = table.snapshot();
3987
+ let closed = false;
3988
+ const live = (what) => {
3989
+ if (closed) throw hostError(label, REFUSALS.transactionFinished.refusal.replace("{label}", label).replace("{what}", what));
3990
+ };
3991
+ const handle = {
3992
+ query: async (sql, params) => {
3993
+ live("query");
3994
+ return (await op("tx.query", {
3995
+ id,
3996
+ sql: String(sql),
3997
+ params: params ?? []
3998
+ }, (a) => read(table, String(a.sql), oltpParams(SURFACES.tx, a.params)))).rows;
3999
+ },
4000
+ exec: async (sql, params) => {
4001
+ live("exec");
4002
+ return (await op("tx.exec", {
4003
+ id,
4004
+ sql: String(sql),
4005
+ params: params ?? []
4006
+ }, (a) => ({ rowCount: table.exec(String(a.sql), oltpParams(SURFACES.tx, a.params)) }))).rowCount;
4007
+ }
4008
+ };
4009
+ let result;
4010
+ try {
4011
+ result = await fn(handle);
4012
+ } catch (err) {
4013
+ closed = true;
4014
+ if (incremented) open--;
4015
+ try {
4016
+ await op("tx.rollback", { id }, () => {
4017
+ restore();
4018
+ return {};
4019
+ });
4020
+ } catch {}
4021
+ throw err;
4022
+ }
4023
+ closed = true;
4024
+ if (incremented) open--;
4025
+ await op("tx.commit", { id }, () => ({}));
4026
+ return result;
4027
+ }
4028
+ const ctx = {
4029
+ user: {
4030
+ ...DEFAULT_USER,
4031
+ ...options.user
4032
+ },
4033
+ env: { ...options.env ?? {} },
4034
+ log: () => {},
4035
+ crypto: nodeCrypto(),
4036
+ query: async (sql) => await op("query", { sql: String(sql) }, (a) => read(state.warehouse(defaultDatabase()), String(a.sql))),
4037
+ queryStream: async function* (sql, opts) {
4038
+ const batchSize = opts?.batchSize || 1e3;
4039
+ const rows = await op("query_stream", { sql: String(sql) }, (a) => {
4040
+ const { rows, __source } = read(state.warehouse(defaultDatabase()), String(a.sql));
4041
+ return Object.assign(rows, { __source });
4042
+ });
4043
+ for (let i = 0; i < rows.length; i += batchSize) yield rows.slice(i, i + batchSize);
4044
+ },
4045
+ fetch: (url, init) => op("fetch", {
4046
+ url,
4047
+ init: init ?? {}
4048
+ }, (a) => fetchOp(String(a.url), a.init ?? {})),
4049
+ warehouse: {
4050
+ insert: (database, table, rows) => op("warehouse.insert", {
4051
+ database,
4052
+ table,
4053
+ rows
4054
+ }, (a) => {
4055
+ checkWriteDestination(SURFACES.warehouse, String(a.database), false);
4056
+ state.warehouse(String(a.database)).append(String(a.table), a.rows);
4057
+ return { ok: true };
4058
+ }),
4059
+ exec: (database, sql) => op("warehouse.exec", {
4060
+ database,
4061
+ sql
4062
+ }, (a) => {
4063
+ checkWriteDestination(SURFACES.warehouse, String(a.database), false);
4064
+ state.warehouse(String(a.database)).exec(String(a.sql));
4065
+ return { ok: true };
4066
+ }),
4067
+ upsert: (database, table, rows, conflictColumns) => op("warehouse.upsert", {
4068
+ database,
4069
+ table,
4070
+ rows,
4071
+ conflictColumns
4072
+ }, (a) => {
4073
+ const database = String(a.database);
4074
+ const db = checkWriteDestination(SURFACES.warehouse, database, false);
4075
+ if (!DIALECTS[db.dialect].parsesOnConflict) throw refuse(SURFACES.warehouse, REFUSALS.upsertUnsupported, { dialect: DIALECTS[db.dialect].name });
4076
+ if (db.kind === "airhouse" || db.kind === "airhouse_managed") throw contextError(`@oxy-hq/sdk/testing: ctx.warehouse.upsert on "${database}" would be refused by the ENGINE, not the host. Airhouse is DuckLake, and a DuckLake table cannot carry the primary key or unique constraint that INSERT … ON CONFLICT needs, so the statement the host lets through fails at runtime. Use ctx.airhouse.append and keep one row per id on read. (These are the test context's words, not a host refusal — assert that the call was refused, not on this text, which may be reworded.)`);
4077
+ state.warehouse(database).append(String(a.table), a.rows);
4078
+ return { ok: true };
4079
+ }),
4080
+ query: (database, sql) => op("warehouse.query", {
4081
+ database,
4082
+ sql
4083
+ }, (a) => {
4084
+ const database = String(a.database);
4085
+ if (!databases[database]) throw refuse(SURFACES.warehouse, REFUSALS.databaseNotConfigured, { database });
4086
+ return read(state.warehouse(database), String(a.sql));
4087
+ })
4088
+ },
4089
+ tx: (database, fn) => runTx("ctx.tx(database, fn)", SURFACES.tx, "tx.begin", { database: String(database) }, fn),
4090
+ oltp: {
4091
+ tx: (fn) => runTx("ctx.oltp.tx(fn)", "ctx.oltp.tx", "tx.begin_oltp", {}, fn),
4092
+ query: async (sql, params) => {
4093
+ return (await op("oltp.query", {
4094
+ sql: String(sql),
4095
+ params: params ?? []
4096
+ }, (a) => read(requireOltp(SURFACES.oltp), String(a.sql), oltpParams(SURFACES.oltp, a.params)))).rows;
4097
+ },
4098
+ exec: async (sql, params) => {
4099
+ return (await op("oltp.exec", {
4100
+ sql: String(sql),
4101
+ params: params ?? []
4102
+ }, (a) => ({ rowCount: requireOltp(SURFACES.oltp).exec(String(a.sql), oltpParams(SURFACES.oltp, a.params)) }))).rowCount;
4103
+ }
4104
+ },
4105
+ airhouse: {
4106
+ schema: gates.airhouse ? gates.writerSchema : null,
4107
+ query: (sql) => op("airhouse.query", { sql: String(sql) }, (a) => read(requireAirhouse(), String(a.sql))),
4108
+ exec: async (sql) => {
4109
+ await op("airhouse.exec", { sql: String(sql) }, (a) => {
4110
+ requireAirhouse().exec(String(a.sql));
4111
+ return { ok: true };
4112
+ });
4113
+ },
4114
+ append: async (table, rows) => {
4115
+ return (await op("airhouse.append", {
4116
+ table: String(table),
4117
+ rows
4118
+ }, (a) => ({ rowCount: requireAirhouse().append(String(a.table), a.rows) }))).rowCount;
4119
+ }
4120
+ },
4121
+ secrets: { set: async (key, value) => {
4122
+ await op("secrets.set", {
4123
+ key: String(key),
4124
+ value: String(value)
4125
+ }, (a) => {
4126
+ if (!gates.secretsWrite) throw refuse(SURFACES.secretsSet, REFUSALS.secretsWrite);
4127
+ state.secrets.set(String(a.key), String(a.value));
4128
+ return null;
4129
+ });
4130
+ } },
4131
+ email: { send: (input) => op("email.send", { ...input }, (a) => {
4132
+ if (!gates.emailSend) throw refuse(SURFACES.emailSend, REFUSALS.emailSend);
4133
+ state.emails.push(a);
4134
+ return { messageId: `message-${state.emails.length}` };
4135
+ }) },
4136
+ org: {
4137
+ people: () => op("org.people", {}, () => {
4138
+ if (!gates.orgRead) throw refuse(SURFACES.orgPeople, REFUSALS.orgPeople);
4139
+ return {
4140
+ people: [...state.org.people],
4141
+ total: state.org.people.length
4142
+ };
4143
+ }),
4144
+ places: () => op("org.places", {}, () => {
4145
+ if (!gates.orgRead) throw refuse(SURFACES.orgPlaces, REFUSALS.orgMember, { member: "places" });
4146
+ return {
4147
+ total: state.org.places.length,
4148
+ places: [...state.org.places]
4149
+ };
4150
+ }),
4151
+ assignments: () => op("org.assignments", {}, () => {
4152
+ if (!gates.orgRead) throw refuse(SURFACES.orgAssignments, REFUSALS.orgMember, { member: "assignments" });
4153
+ return {
4154
+ total: state.org.assignments.length,
4155
+ assignments: [...state.org.assignments]
4156
+ };
4157
+ })
4158
+ },
4159
+ storage: storageApi(),
4160
+ semantic: { query: (spec) => op("semantic.query", { spec }, (a) => {
4161
+ if (!semanticAnswer) throw contextError("ctx.semantic.query has no answer registered: the zoo pins no semantic payload, so supply one with t.state.semantic.on((spec) => result)");
4162
+ return semanticAnswer(a.spec);
4163
+ }) },
4164
+ airway: { run: (pipelineRef, variables) => op("airway.run", {
4165
+ pipelineRef: String(pipelineRef),
4166
+ variables: variables ?? null
4167
+ }, (a) => {
4168
+ state.airway.runs.push({
4169
+ pipelineRef: String(a.pipelineRef),
4170
+ variables: a.variables
4171
+ });
4172
+ return { runId: `run-${state.airway.runs.length}` };
4173
+ }) }
4174
+ };
4175
+ function fetchOp(url, init) {
4176
+ let parsed;
4177
+ try {
4178
+ parsed = new URL(url);
4179
+ } catch (e) {
4180
+ throw refuse(SURFACES.fetch, REFUSALS.fetchInvalidUrl, { e: e instanceof Error ? e.message : String(e) });
4181
+ }
4182
+ if (!isSafeOutbound(parsed)) throw refuse(SURFACES.fetch, REFUSALS.fetchBlocked, { url });
4183
+ for (const [k, v] of Object.entries(headersOf(init.headers))) {
4184
+ if (!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(k)) throw refuse(SURFACES.fetch, REFUSALS.fetchInvalidHeaderName, { k });
4185
+ if (/[\r\n\0]/.test(v)) throw refuse(SURFACES.fetch, REFUSALS.fetchInvalidHeaderValue, { k });
4186
+ }
4187
+ state.fetch.received.push({
4188
+ url,
4189
+ init
4190
+ });
4191
+ const answer = state.fetch.answerFor(url);
4192
+ if (answer === void 0) throw contextError(`ctx.fetch has no answer for ${url}: register one with t.state.fetch.on(url, { status, body }) — nothing here reaches the network`);
4193
+ const reply = typeof answer === "function" ? answer(url, init) : answer;
4194
+ const fixture = reply.body ?? "";
4195
+ const fixtureIsBase64 = reply.encoding === "base64";
4196
+ const max = gates.fetchMaxBytes ?? 10485760;
4197
+ const len = fixtureIsBase64 ? base64ByteLength(fixture) : encoder.encode(fixture).length;
4198
+ if (len > max) throw refuse(SURFACES.fetch, REFUSALS.fetchTooLarge, {
4199
+ len,
4200
+ max_bytes: max
4201
+ });
4202
+ if (init.encoding !== void 0 && init.encoding !== "utf8" && init.encoding !== "base64") throw contextError(`ctx.fetch: unknown encoding '${String(init.encoding)}' (expected 'utf8' or 'base64')`);
4203
+ const wantBase64 = init.encoding === "base64";
4204
+ const body = wantBase64 ? fixtureIsBase64 ? fixture : utf8ToBase64(fixture) : fixtureIsBase64 ? base64ToUtf8(fixture) : fixture;
4205
+ return {
4206
+ status: reply.status ?? 200,
4207
+ body,
4208
+ encoding: wantBase64 ? "base64" : "utf8"
4209
+ };
4210
+ }
4211
+ function storageApi() {
4212
+ const now = () => (/* @__PURE__ */ new Date()).toISOString();
4213
+ const put = (key, body, contentType) => {
4214
+ const object = {
4215
+ key,
4216
+ body,
4217
+ contentType,
4218
+ size: base64ByteLength(body),
4219
+ lastModified: now()
4220
+ };
4221
+ state.storage.set(key, object);
4222
+ return object;
4223
+ };
4224
+ const storageOp = (name, args, impl) => op(`storage.${name}`, args, (a) => {
4225
+ requireStorage(name);
4226
+ return impl(a);
4227
+ });
4228
+ return {
4229
+ getUploadUrl: (opts) => storageOp("getUploadUrl", { ...opts }, (a) => {
4230
+ const key = `${String(a.pathname ?? `uploads/${String(a.filename ?? "upload")}`).replace(/(\.[^.]*)?$/, `-${randomSuffix()}$1`)}`;
4231
+ return {
4232
+ url: `https://storage.example.test/put/${key}`,
4233
+ key,
4234
+ expiresAt: now()
4235
+ };
4236
+ }),
4237
+ getDownloadUrl: (key, opts) => storageOp("getDownloadUrl", {
4238
+ key: String(key),
4239
+ ...opts
4240
+ }, (a) => ({
4241
+ url: `https://storage.example.test/get/${String(a.key)}`,
4242
+ expiresAt: now()
4243
+ })),
4244
+ put: (pathname, body, opts) => storageOp("put", {
4245
+ pathname: String(pathname),
4246
+ body: String(body),
4247
+ ...opts
4248
+ }, (a) => {
4249
+ const key = a.addRandomSuffix ? String(a.pathname).replace(/(\.[^.]*)?$/, `-${randomSuffix()}$1`) : String(a.pathname);
4250
+ if (state.storage.has(key) && !a.allowOverwrite) throw hostError(SURFACES.storage, `put: "${key}" already exists (pass allowOverwrite: true)`);
4251
+ const base64 = a.encoding === "base64" ? String(a.body) : utf8ToBase64(String(a.body));
4252
+ const stored = put(key, base64, a.contentType ?? null);
4253
+ return {
4254
+ key,
4255
+ size: stored.size,
4256
+ contentType: stored.contentType ?? "application/octet-stream"
4257
+ };
4258
+ }),
4259
+ get: (key, opts) => storageOp("get", {
4260
+ key: String(key),
4261
+ ...opts
4262
+ }, (a) => {
4263
+ const object = state.storage.get(String(a.key));
4264
+ if (!object) return null;
4265
+ const base64 = a.encoding === "base64";
4266
+ return {
4267
+ body: base64 ? object.body : base64ToUtf8(object.body),
4268
+ contentType: object.contentType,
4269
+ size: object.size,
4270
+ encoding: base64 ? "base64" : "utf8"
4271
+ };
4272
+ }),
4273
+ head: (key) => storageOp("head", { key: String(key) }, (a) => {
4274
+ const object = state.storage.get(String(a.key));
4275
+ return object ? {
4276
+ key: object.key,
4277
+ size: object.size,
4278
+ contentType: object.contentType,
4279
+ lastModified: object.lastModified
4280
+ } : null;
4281
+ }),
4282
+ list: (opts) => storageOp("list", { ...opts }, (a) => {
4283
+ const prefix = String(a.prefix ?? "");
4284
+ const limit = Number(a.limit ?? 1e3);
4285
+ const offset = a.cursor ? Number(a.cursor) : 0;
4286
+ const keys = [...state.storage.keys()].filter((k) => k.startsWith(prefix)).sort();
4287
+ const page = keys.slice(offset, offset + limit).map((k) => {
4288
+ const o = state.storage.get(k);
4289
+ return {
4290
+ key: o.key,
4291
+ size: o.size,
4292
+ contentType: o.contentType,
4293
+ lastModified: o.lastModified
4294
+ };
4295
+ });
4296
+ const hasMore = offset + limit < keys.length;
4297
+ return {
4298
+ objects: page,
4299
+ cursor: hasMore ? String(offset + limit) : null,
4300
+ hasMore
4301
+ };
4302
+ }),
4303
+ delete: (keyOrKeys) => storageOp("delete", Array.isArray(keyOrKeys) ? { keys: keyOrKeys.map(String) } : { key: String(keyOrKeys) }, (a) => {
4304
+ const keys = Array.isArray(a.keys) ? a.keys : [String(a.key)];
4305
+ for (const k of keys) state.storage.delete(k);
4306
+ return { deleted: keys.length };
4307
+ }),
4308
+ copy: (fromKey, toPathname, opts) => storageOp("copy", {
4309
+ fromKey: String(fromKey),
4310
+ toPathname: String(toPathname),
4311
+ ...opts
4312
+ }, (a) => {
4313
+ const from = state.storage.get(String(a.fromKey));
4314
+ if (!from) throw hostError(SURFACES.storage, `copy: "${String(a.fromKey)}" does not exist`);
4315
+ const key = String(a.toPathname);
4316
+ if (state.storage.has(key) && !a.allowOverwrite) throw hostError(SURFACES.storage, `copy: "${key}" already exists (pass allowOverwrite: true)`);
4317
+ const stored = put(key, from.body, from.contentType);
4318
+ return {
4319
+ key,
4320
+ size: stored.size,
4321
+ contentType: stored.contentType ?? "application/octet-stream"
4322
+ };
4323
+ })
4324
+ };
4325
+ }
4326
+ return {
4327
+ ctx,
4328
+ calls,
4329
+ ops: () => [...new Set(calls.map((c) => c.op))],
4330
+ callsTo: (name) => calls.filter((c) => c.op === name),
4331
+ override: (name, impl) => {
4332
+ overrides.set(name, impl);
4333
+ },
4334
+ run: runWithoutIsolateGlobals,
4335
+ state,
4336
+ gates
4337
+ };
4338
+ }
4339
+ function headersOf(headers) {
4340
+ if (!headers) return {};
4341
+ if (Array.isArray(headers)) return Object.fromEntries(headers);
4342
+ if (typeof Headers !== "undefined" && headers instanceof Headers) return Object.fromEntries(headers.entries());
4343
+ return headers;
4344
+ }
4345
+ function randomSuffix() {
4346
+ return Math.random().toString(36).slice(2, 8);
4347
+ }
4348
+ /**
4349
+ * Bytes a base64 string decodes to. `length * 3 / 4` overstates by the padding,
4350
+ * which made `size` wrong by up to two bytes and fired the `ctx.fetch` cap early.
4351
+ */
4352
+ function base64ByteLength(base64) {
4353
+ const s = base64.trim();
4354
+ if (s === "") return 0;
4355
+ const padding = s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0;
4356
+ return Math.floor(s.length * 3 / 4) - padding;
4357
+ }
4358
+ function utf8ToBase64(text) {
4359
+ const bytes = encoder.encode(text);
4360
+ let binary = "";
4361
+ for (const b of bytes) binary += String.fromCharCode(b);
4362
+ return nodeBtoa(binary);
4363
+ }
4364
+ function base64ToUtf8(base64) {
4365
+ const binary = nodeAtob(base64);
4366
+ const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
4367
+ return decoder.decode(bytes);
4368
+ }
4369
+ /**
4370
+ * `ctx.crypto` over `node:crypto`: the same three synchronous members
4371
+ * `__buildCtx` binds, with the host's argument rules (`key` and `data`
4372
+ * required; `signature` and both sides of `timingSafeEqual` lenient). A digest
4373
+ * is ASCII, so the byte views need no `Buffer` — which `t.run` removes.
4374
+ */
4375
+ function nodeCrypto() {
4376
+ const lib = () => nodeCryptoModule;
4377
+ const ascii = (s) => Uint8Array.from(s, (c) => c.charCodeAt(0));
4378
+ const digest = (algorithm, key, data, encoding) => lib().createHmac(algorithm, key).update(data).digest(encoding);
4379
+ const same = (a, b) => a !== "" && b !== "" && a.length === b.length && lib().timingSafeEqual(ascii(a), ascii(b));
4380
+ return {
4381
+ hmac: ({ algorithm, key, data, encoding }) => {
4382
+ if (key == null) throw new TypeError("ctx.crypto.hmac: `key` is required — is the secret set?");
4383
+ if (data == null) throw new TypeError("ctx.crypto.hmac: `data` is required");
4384
+ return digest(algorithm ?? "sha256", String(key), String(data), encoding ?? "hex");
4385
+ },
4386
+ verifyHmac: ({ algorithm, key, data, signature, encoding }) => {
4387
+ if (key == null) throw new TypeError("ctx.crypto.verifyHmac: `key` is required — is the secret set?");
4388
+ if (data == null) throw new TypeError("ctx.crypto.verifyHmac: `data` is required");
4389
+ const expected = digest(algorithm ?? "sha256", String(key), String(data), encoding ?? "hex");
4390
+ return same(String(signature ?? ""), expected);
4391
+ },
4392
+ timingSafeEqual: (a, b) => same(a == null ? "" : String(a), b == null ? "" : String(b))
4393
+ };
4394
+ }
4395
+
4396
+ //#endregion
4397
+ exports.ABSENT_GLOBALS = ABSENT_GLOBALS;
4398
+ exports.DIALECTS = DIALECTS;
4399
+ exports.FETCH_MAX_BYTES = FETCH_MAX_BYTES;
4400
+ exports.FETCH_RULES = FETCH_RULES;
4401
+ exports.FetchStore = FetchStore;
4402
+ exports.GATES = GATES;
4403
+ exports.HOST_ERROR_NAME = HOST_ERROR_NAME;
4404
+ exports.HOST_OPS = HOST_OPS;
4405
+ exports.MAX_OPEN_TRANSACTIONS = MAX_OPEN_TRANSACTIONS;
4406
+ exports.REFUSALS = REFUSALS;
4407
+ exports.SURFACES = SURFACES;
4408
+ exports.TableStore = TableStore;
4409
+ exports.TypedTable = TypedTable;
4410
+ exports.ZOO = ZOO;
4411
+ exports.ZOO_SHA256 = ZOO_SHA256;
4412
+ exports.ZooRefusal = ZooRefusal;
4413
+ exports.casesFor = casesFor;
4414
+ exports.contextError = contextError;
4415
+ exports.createTestContext = createTestContext;
4416
+ exports.expectation = expectation;
4417
+ exports.hostError = hostError;
4418
+ exports.isHostError = isHostError;
4419
+ exports.isSafeOutbound = isSafeOutbound;
4420
+ exports.isolateAtob = isolateAtob;
4421
+ exports.isolateBtoa = isolateBtoa;
4422
+ exports.knownTypes = knownTypes;
4423
+ exports.readGates = readGates;
4424
+ exports.refuse = refuse;
4425
+ exports.render = render;
4426
+ exports.renderValue = renderValue;
4427
+ exports.runWithoutIsolateGlobals = runWithoutIsolateGlobals;
4428
+ exports.writerSchema = writerSchema;
4429
+ exports.zooColumn = zooColumn;
4430
+ exports.zooTableName = zooTableName;
4431
+ //# sourceMappingURL=testing.cjs.map