Repository navigation
Conversation
JSON_ARRAY returns every cell as a string, so analytics query rows carried "42" for BIGINT, "1.50" for DECIMAL and "true" for BOOLEAN while the generated query types promise number and boolean. The SQL warehouse connector now attaches the manifest column types next to the column names it already carries, and the /query route converts numeric and BOOLEAN cells on both the native JSON_ARRAY path and the ARROW_STREAM fallback. NULL, date/time and nested values are unchanged, and the /metric route keeps its documented string | null wire values. Remove the dev-playground's number-coercion workarounds in the KPI cards. Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: Fabian Jakobs <fabian.jakobs@databricks.com>
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 1.3 MB (+2.6 KB) | 460 KB (+934 B) |
| Type declarations | 465 KB | 169 KB (+1 B) |
| Source maps | 2.5 MB (+4.4 KB) | 860 KB (+1.4 KB) |
| Other | 11 KB | 3.7 KB |
| Total | 4.3 MB (+6.9 KB) | 1.5 MB (+2.3 KB) |
Per-entry composition (own code — deps external (as shipped))
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
. |
107 KB (+287 B) | 2.5 KB | 109 KB (+287 B) | external | 345 KB (+645 B) |
./beta |
103 KB (+35 B) | 482 B | 104 KB (+35 B) | external | 310 KB (+154 B) |
./testing |
45 KB | 32 KB | 77 KB | external | 223 KB |
./tsdown |
520 B | 0 B | 520 B | external | 813 B |
./type-generator |
26 KB | 0 B | 26 KB | external | 74 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
. |
index.js |
initial | 102 KB |
. |
utils.js |
initial | 4.6 KB |
. |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./beta |
beta.js |
initial | 83 KB |
./beta |
modular.js |
initial | 6.0 KB |
./beta |
stream-manager.js |
initial | 5.9 KB |
./beta |
service-context.js |
initial | 4.2 KB |
./beta |
databricks.js |
initial | 3.3 KB |
./beta |
client.js |
initial | 647 B |
./beta |
index.js |
initial | 20 B |
./beta |
supervisor-api.js |
lazy | 192 B |
./beta |
databricks.js |
lazy | 176 B |
./beta |
index.js |
lazy | 114 B |
./testing |
manifest.js |
initial | 32 KB |
./testing |
index.js |
initial | 10 KB |
./testing |
wide-event-emitter.js |
initial | 2.9 KB |
./testing |
index.js |
lazy | 28 KB |
./testing |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./testing |
utils.js |
lazy | 1.8 KB |
./tsdown |
index.js |
initial | 520 B |
./type-generator |
index.js |
initial | 26 KB |
@databricks/appkit-ui
npm tarball (packed): 397 KB — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 429 KB | 147 KB |
| Type declarations | 267 KB | 98 KB |
| Source maps | 853 KB | 286 KB |
| CSS | 16 KB | 3.2 KB |
| Total | 1.5 MB | 534 KB |
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
./js |
5.3 KB | 49 KB | 55 KB | 208 KB | 14 KB |
./js/beta |
2.1 KB | 0 B | 2.1 KB | 0 B | 5.0 KB |
./react |
433 KB | 49 KB | 481 KB | 1.3 MB | 177 KB |
./react/beta |
4.9 KB | 0 B | 4.9 KB | 0 B | 12 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
./js |
index.js |
initial | 5.2 KB |
./js |
chunk |
initial | 120 B |
./js |
apache-arrow |
lazy | 49 KB |
./js/beta |
beta.js |
initial | 2.1 KB |
./react |
index.js |
initial | 431 KB |
./react |
tslib |
initial | 2.1 KB |
./react |
apache-arrow |
lazy | 49 KB |
./react/beta |
beta.js |
initial | 4.9 KB |
🤖 AppKit PR bot🔬 Run evalsStart an eval for this PR from the evals-monitor app: Go to Evals Monitor → 📦 Try this PR's app templateScaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh run download 42247154360 -R databricks/appkit -n appkit-template-0.90.0-pr.fbfc70a-fjakobs-la-2230-numeric-types-709 -D appkit-pr-709 \
&& unzip -o "appkit-pr-709/appkit-template-0.90.0-pr.fbfc70a-fjakobs-la-2230-numeric-types-709.zip" -d "appkit-pr-709" \
&& databricks apps init --template "appkit-pr-709"The template pins |
Under JSON_ARRAY the warehouse returns DOUBLE and FLOAT NaN and ±Infinity as "NaN", "Infinity" and "-Infinity". The /query coercion turned them into NaN/Infinity numbers, which the SSE JSON then sent as null, the same value as SQL NULL. Numeric cells that don't parse to a finite number now keep the warehouse string, since JSON has no number for them. Co-authored-by: Isaac <no-reply@databricks.com> Signed-off-by: Fabian Jakobs <fabian.jakobs@databricks.com>
|
@pffigueiredo thanks for the review. I replied in your thread, which is resolved and so collapsed: #709 (comment) Short version: I kept plain |
Why
numberand BOOLEAN columns asbooleaninanalytics.d.ts./queryroute returns them as strings. The warehouse's JSON_ARRAY format sends every cell as a string, and the connector passed them through unchanged.useAnalyticsQueryrows hadtotal_trips: "21932"while the type saidnumber. Apps (and agents writing apps) kept adding their ownNumber(...)workarounds. The dev-playground did the same in its KPI cards.Reproduced on e2-dogfood (Serverless Starter Warehouse). This is a query run through the real type generator and the connector's JSON_ARRAY path:
BIGINTnumber"42"DECIMAL(10,2)number"1.50"INT/SMALLINT/TINYINTnumber"7"/"3"/"1"DOUBLE/FLOATnumber"2.5"/"1.25"BOOLEANboolean"true"Change
columnTypes) next to thecolumnNamesit already carries. It does this on JSON rows and on inline Arrow results. Cell values are unchanged at this layer.deliverJsonResulttakes acoerceScalarsoption. With it set,coerceScalarCellsconverts cells by manifesttypeName:BYTE,SHORT,INT,LONG,FLOAT,DOUBLEandDECIMALbecome numbers.BOOLEANbecomes a boolean./queryroute setscoerceScalars. The/metricroute keeps its documentedstring | nullwire values, so metric-view types and docs don't change.null. DATE and TIMESTAMP stay ISO strings. STRUCT, ARRAY and MAP values stay as delivered.NaN,Infinityand-Infinitystay the strings"NaN","Infinity"and"-Infinity". JSON has no number for them, and converting them would putnullon the wire, the same as SQL NULL.toNumand the other string-coercion guards inkpi-cards.tsx.type-generation.md.Trade-offs
BIGINTbeyondNumber.MAX_SAFE_INTEGERand aDECIMALbeyond about 15 significant digits lose precision as JS numbers.DECIMALalso loses trailing zeros ("1.50"becomes1.5). The docs say toCAST(... AS STRING)for exact values. The generated type then becomesstring, so it stays truthful./query: they become what the generated types already claimed. Code that relied on getting strings at runtime will see numbers.unknown[]orRecord<string, unknown>.Testing
columnNamesandcolumnTypesare attached.deliverJsonResult: native path, Reyden fallback using the captured fixture, and no conversion without the option./queryroute: converts values./metricroute: keeps strings.pnpm build,pnpm docs:build,pnpm check:fix,pnpm -r typecheckandpnpm testall pass (5934 tests).POST /api/analytics/query/dashboard_kpisnow returns{"total_trips":21932,"avg_fare":12.35,…}.trip_datestays"2015-12-31".POST /api/analytics/metric/revenuestill returns{"arr":"1.604847408E9"}.toNum.NaN/±Infinitythrough/query, on both a standard serverless warehouse and a Reyden (REALTIME) warehouse. Every value matches its generated type except the three non-finite strings, and NULLs arenull. Also ran the ARROW_STREAM fallback with live Reyden Arrow bytes (the JSON_ARRAY rejection was simulated, since the warehouse now serves JSON_ARRAY): the same values as native JSON_ARRAY.This pull request and its description were written by Isaac.