@marimo-team/frontend 0.23.10 → 0.23.11-dev10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{CellStatus-e0ex7Iei.js → CellStatus-CLGvVxcw.js} +1 -1
- package/dist/assets/{JsonOutput-DRNPZOvX.js → JsonOutput-uEJijGXp.js} +5 -5
- package/dist/assets/{MarimoErrorOutput-BH6hs0Ir.js → MarimoErrorOutput-DzoKyXWR.js} +2 -2
- package/dist/assets/{RenderHTML-BQ1PO4Wd.js → RenderHTML-DAt48X-F.js} +1 -1
- package/dist/assets/{RunButton-F8pLIvFp.js → RunButton-B7msyyYi.js} +1 -1
- package/dist/assets/{add-cell-with-ai-Bd_3tPEt.js → add-cell-with-ai-CAkcousR.js} +20 -20
- package/dist/assets/{add-connection-dialog-AhwxOztN.js → add-connection-dialog-ZyXXfAVG.js} +32 -32
- package/dist/assets/{agent-panel-Dm0KI1sF.js → agent-panel-BfIguQXh.js} +6 -6
- package/dist/assets/{ai-model-dropdown-CG4B4rqH.js → ai-model-dropdown-rE64ytSX.js} +3 -3
- package/dist/assets/{app-config-button-D_sFrSql.js → app-config-button-DLRZ5d9c.js} +1 -1
- package/dist/assets/{cell-editor-B3aYYyAI.js → cell-editor-2JIpvFn4.js} +15 -12
- package/dist/assets/{cell-link-Bj4-yOIx.js → cell-link-DY95GSb7.js} +1 -1
- package/dist/assets/{cells-DOA0Gew8.js → cells-D-v2lBet.js} +67 -67
- package/dist/assets/{chat-display-DI0jRLIv.js → chat-display-DO-tqsbY.js} +1 -1
- package/dist/assets/{chat-panel-BU4HHdf5.js → chat-panel-BT5gLfs6.js} +2 -2
- package/dist/assets/{chat-ui-C7igY2w5.js → chat-ui-Be4yDBZS.js} +4 -4
- package/dist/assets/column-preview-BzvFdLI5.js +1 -0
- package/dist/assets/{command-palette-Bjv1Z7v8.js → command-palette-CKKzfpGt.js} +1 -1
- package/dist/assets/{common-fDFYY_sv.js → common-Do4N1uVK.js} +1 -1
- package/dist/assets/{components--C6N-DXq.js → components-DUC0f1XD.js} +1 -1
- package/dist/assets/{datasource-CR6RRpTi.js → datasource-BQGI7c_u.js} +2 -2
- package/dist/assets/{dependency-graph-panel-BEgkvdX0.js → dependency-graph-panel-Czoya7c2.js} +1 -1
- package/dist/assets/{documentation-panel-HvbKykbI.js → documentation-panel-LokVYDIZ.js} +1 -1
- package/dist/assets/{download-DhxnAw14.js → download-WGU5w_3m.js} +3 -3
- package/dist/assets/{edit-page-BeWwLeT8.js → edit-page-BPQO1Uuz.js} +6 -6
- package/dist/assets/{error-panel-WLBQ3q9p.js → error-panel-BCm_e4eM.js} +1 -1
- package/dist/assets/{file-explorer-panel-DtzGlnzT.js → file-explorer-panel-D1NN-z8x.js} +3 -3
- package/dist/assets/{file-icons-D2f3nfbq.js → file-icons-CF-YT4hq.js} +1 -1
- package/dist/assets/{file-name-input-BNYf9WWM.js → file-name-input-BRVXQ3OU.js} +1 -1
- package/dist/assets/{floating-outline-BvHFWRoz.js → floating-outline-D33Zu-Ad.js} +1 -1
- package/dist/assets/{focus-Ldqh99xE.js → focus-BfFAxl9X.js} +1 -1
- package/dist/assets/{form-CxBAInfg.js → form-CVBFx2z3.js} +1 -1
- package/dist/assets/{home-page-DwFpLpXK.js → home-page-CL9Hv1Hg.js} +2 -2
- package/dist/assets/{hooks-DyMacA-R.js → hooks-83y0XCiC.js} +1 -1
- package/dist/assets/{html-to-image-CyAtzePO.js → html-to-image-IPNqWX7V.js} +2 -2
- package/dist/assets/index-BNWrEIlp.css +2 -0
- package/dist/assets/{index-fNBoXCyz.js → index-CuhY66ZR.js} +14 -14
- package/dist/assets/{kiosk-mode-CTWHjzXs.js → kiosk-mode-BSufcIZH.js} +1 -1
- package/dist/assets/{layout-dRNPwA-7.js → layout-ks0WJ2vR.js} +5 -5
- package/dist/assets/{logs-panel-BVLYycQb.js → logs-panel-DXN6sUaA.js} +1 -1
- package/dist/assets/{markdown-renderer-C9Ujvj0b.js → markdown-renderer-DWRPo52L.js} +1 -1
- package/dist/assets/{name-cell-input-DabvuruX.js → name-cell-input-BiDIx6YQ.js} +1 -1
- package/dist/assets/{outline-panel-B-ncbNWI.js → outline-panel-DVSGNRgP.js} +1 -1
- package/dist/assets/{packages-panel-CESeW_3T.js → packages-panel-DTX6CBnm.js} +1 -1
- package/dist/assets/{panels-BTEEcvYR.js → panels-NhGV0SBq.js} +1 -1
- package/dist/assets/{process-output-pPgH0ANl.js → process-output-BiWV34b7.js} +1 -1
- package/dist/assets/{radio-group-D7rh6Zek.js → radio-group-DV-lQvil.js} +1 -1
- package/dist/assets/{readonly-python-code-CvPx4CU_.js → readonly-python-code-B0glFTKW.js} +1 -1
- package/dist/assets/{reveal-component-DGQQBmed.js → reveal-component-C2M2FixA.js} +12 -12
- package/dist/assets/{run-page-yFxABzXq.js → run-page-B6I-Lshx.js} +1 -1
- package/dist/assets/{scratchpad-panel-B_nxW99u.js → scratchpad-panel-DU7perVk.js} +1 -1
- package/dist/assets/session-panel-B4UTmf-j.js +1 -0
- package/dist/assets/{snippets-panel-BSgcoo-M.js → snippets-panel-KRdl4bVk.js} +1 -1
- package/dist/assets/{state-BWM3qRkR.js → state-BSm0OM93.js} +1 -1
- package/dist/assets/{state-C8yHPSLN.js → state-CbkvENzk.js} +2 -2
- package/dist/assets/{textarea-bBuxbFm7.js → textarea-CBbixTxi.js} +1 -1
- package/dist/assets/{tracing-pt7eDHWc.js → tracing-D8LGpuXa.js} +1 -1
- package/dist/assets/{tracing-panel-BveZ5DZw.js → tracing-panel-TUP6kAd5.js} +2 -2
- package/dist/assets/{tree-actions-1KQDSu1H.js → tree-actions-BvrKFU0g.js} +1 -1
- package/dist/assets/{useCellActionButton-C4V7J6PS.js → useCellActionButton-CtOZIXD0.js} +1 -1
- package/dist/assets/{useDeleteCell-BvnurAZ9.js → useDeleteCell-BLvzLWAT.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-DNlXaxbt.js → useDependencyPanelTab-BP0sNfUz.js} +1 -1
- package/dist/assets/{useNotebookActions-Dw6tY2qa.js → useNotebookActions-BI5dWutQ.js} +1 -1
- package/dist/assets/{useRunCells-cSZpNqnR.js → useRunCells-BClkx9Pq.js} +1 -1
- package/dist/assets/{useSplitCell-s7dSiBUa.js → useSplitCell-CpddCX_u.js} +1 -1
- package/dist/index.html +23 -23
- package/package.json +1 -1
- package/src/components/datasources/__tests__/column-preview.test.tsx +97 -0
- package/src/components/datasources/__tests__/filter-empty.test.ts +81 -0
- package/src/components/datasources/__tests__/utils.test.ts +62 -1
- package/src/components/datasources/column-preview.tsx +2 -4
- package/src/components/datasources/components.tsx +15 -7
- package/src/components/datasources/datasources.tsx +311 -178
- package/src/components/datasources/utils.ts +40 -1
- package/src/components/editor/ai/ai-completion-editor.tsx +6 -5
- package/src/components/editor/connections/components.tsx +13 -0
- package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +4 -4
- package/src/components/editor/connections/storage/as-code.ts +11 -4
- package/src/core/ai/__tests__/strip-wrapping-backticks.test.ts +133 -0
- package/src/core/ai/stream-completion-text.ts +48 -0
- package/src/core/ai/strip-wrapping-backticks.ts +88 -0
- package/src/core/cells/__tests__/cells.test.ts +33 -0
- package/src/core/cells/cells.ts +1 -1
- package/src/core/codemirror/ai/request.ts +2 -14
- package/src/core/datasets/__tests__/data-source.test.ts +226 -0
- package/src/core/datasets/data-source-connections.ts +88 -24
- package/dist/assets/column-preview-nu3Qo2OW.js +0 -1
- package/dist/assets/index-BAYF7dcV.css +0 -2
- package/dist/assets/session-panel-CTJPYbAa.js +0 -1
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
3
3
|
import { variableName } from "@/__tests__/branded";
|
|
4
4
|
import type { DatabaseSchema, DataTable } from "@/core/kernel/messages";
|
|
5
|
+
import { store } from "@/core/state/jotai";
|
|
5
6
|
import type { VariableName } from "@/core/variables/types";
|
|
6
7
|
import {
|
|
8
|
+
allTablesAtom,
|
|
7
9
|
type DataSourceConnection,
|
|
10
|
+
dataSourceConnectionsAtom,
|
|
8
11
|
type DataSourceState,
|
|
9
12
|
exportedForTesting,
|
|
10
13
|
type SQLTableContext,
|
|
@@ -575,3 +578,226 @@ describe("add table", () => {
|
|
|
575
578
|
expect(db1?.schemas.length).toBe(1);
|
|
576
579
|
});
|
|
577
580
|
});
|
|
581
|
+
|
|
582
|
+
describe("nested namespaces", () => {
|
|
583
|
+
// Iceberg-style: database "top" with a schemaless schema and a nested
|
|
584
|
+
// namespace "nested" that has a deferred child namespace "deep".
|
|
585
|
+
const nestedConnections: DataSourceConnection[] = [
|
|
586
|
+
{
|
|
587
|
+
name: "ice" as ConnectionName,
|
|
588
|
+
source: "iceberg",
|
|
589
|
+
display_name: "Iceberg",
|
|
590
|
+
dialect: "iceberg",
|
|
591
|
+
databases: [
|
|
592
|
+
{
|
|
593
|
+
name: "top",
|
|
594
|
+
dialect: "iceberg",
|
|
595
|
+
schemas_resolved: true,
|
|
596
|
+
schemas: [
|
|
597
|
+
{ name: "", tables: [], tables_resolved: true },
|
|
598
|
+
{
|
|
599
|
+
name: "nested",
|
|
600
|
+
tables: [],
|
|
601
|
+
tables_resolved: false,
|
|
602
|
+
child_schemas: [],
|
|
603
|
+
child_schemas_resolved: false,
|
|
604
|
+
},
|
|
605
|
+
],
|
|
606
|
+
},
|
|
607
|
+
],
|
|
608
|
+
},
|
|
609
|
+
];
|
|
610
|
+
|
|
611
|
+
let baseState: DataSourceState;
|
|
612
|
+
|
|
613
|
+
beforeEach(() => {
|
|
614
|
+
baseState = addConnection(nestedConnections, initialState());
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const findSchema = (
|
|
618
|
+
state: DataSourceState,
|
|
619
|
+
path: string[],
|
|
620
|
+
): DatabaseSchema | undefined => {
|
|
621
|
+
const conn = state.connectionsMap.get("ice" as ConnectionName);
|
|
622
|
+
const db = conn?.databases.find((d) => d.name === "top");
|
|
623
|
+
let schemas = db?.schemas ?? [];
|
|
624
|
+
let found: DatabaseSchema | undefined;
|
|
625
|
+
for (const segment of path) {
|
|
626
|
+
found = schemas.find((s) => s.name === segment);
|
|
627
|
+
schemas = found?.child_schemas ?? [];
|
|
628
|
+
}
|
|
629
|
+
return found;
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
it("sets child namespaces at a nested path", () => {
|
|
633
|
+
const children: DatabaseSchema[] = [
|
|
634
|
+
{ name: "deep", tables: [], tables_resolved: false },
|
|
635
|
+
];
|
|
636
|
+
const newState = reducer(baseState, {
|
|
637
|
+
type: "addSchemaList",
|
|
638
|
+
payload: {
|
|
639
|
+
schemas: children,
|
|
640
|
+
sqlSchemaContext: {
|
|
641
|
+
engine: "ice",
|
|
642
|
+
database: "top",
|
|
643
|
+
schemaPath: ["nested"],
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
const nested = findSchema(newState, ["nested"]);
|
|
649
|
+
expect(nested?.child_schemas_resolved).toBe(true);
|
|
650
|
+
expect(nested?.child_schemas?.map((s) => s.name)).toEqual(["deep"]);
|
|
651
|
+
// The schemaless sibling is untouched.
|
|
652
|
+
expect(findSchema(newState, [""])?.name).toBe("");
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it("sets tables at a nested path", () => {
|
|
656
|
+
const tables: DataTable[] = [
|
|
657
|
+
{
|
|
658
|
+
name: "table4",
|
|
659
|
+
columns: [],
|
|
660
|
+
num_columns: 0,
|
|
661
|
+
num_rows: 0,
|
|
662
|
+
variable_name: null,
|
|
663
|
+
source: "iceberg",
|
|
664
|
+
source_type: "catalog",
|
|
665
|
+
type: "table",
|
|
666
|
+
},
|
|
667
|
+
];
|
|
668
|
+
const newState = reducer(baseState, {
|
|
669
|
+
type: "addTableList",
|
|
670
|
+
payload: {
|
|
671
|
+
tables,
|
|
672
|
+
sqlTableContext: {
|
|
673
|
+
engine: "ice",
|
|
674
|
+
database: "top",
|
|
675
|
+
schema: "nested",
|
|
676
|
+
dialect: "iceberg",
|
|
677
|
+
schemaPath: ["nested"],
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
const nested = findSchema(newState, ["nested"]);
|
|
683
|
+
expect(nested?.tables_resolved).toBe(true);
|
|
684
|
+
expect(nested?.tables.map((t) => t.name)).toEqual(["table4"]);
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
it("replaces a single table at a nested path", () => {
|
|
688
|
+
const makeTable = (numRows: number): DataTable => ({
|
|
689
|
+
name: "table4",
|
|
690
|
+
columns: [],
|
|
691
|
+
num_columns: 0,
|
|
692
|
+
num_rows: numRows,
|
|
693
|
+
variable_name: null,
|
|
694
|
+
source: "iceberg",
|
|
695
|
+
source_type: "catalog",
|
|
696
|
+
type: "table",
|
|
697
|
+
});
|
|
698
|
+
const context = {
|
|
699
|
+
engine: "ice",
|
|
700
|
+
database: "top",
|
|
701
|
+
schema: "nested",
|
|
702
|
+
dialect: "iceberg",
|
|
703
|
+
schemaPath: ["nested"],
|
|
704
|
+
};
|
|
705
|
+
let state = reducer(baseState, {
|
|
706
|
+
type: "addTableList",
|
|
707
|
+
payload: { tables: [makeTable(1)], sqlTableContext: context },
|
|
708
|
+
});
|
|
709
|
+
state = reducer(state, {
|
|
710
|
+
type: "addTable",
|
|
711
|
+
payload: { table: makeTable(42), sqlTableContext: context },
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
const nested = findSchema(state, ["nested"]);
|
|
715
|
+
expect(nested?.tables).toHaveLength(1);
|
|
716
|
+
expect(nested?.tables[0].num_rows).toBe(42);
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
it("does not change anything for a missing nested path", () => {
|
|
720
|
+
const newState = reducer(baseState, {
|
|
721
|
+
type: "addSchemaList",
|
|
722
|
+
payload: {
|
|
723
|
+
schemas: [{ name: "deep", tables: [] }],
|
|
724
|
+
sqlSchemaContext: {
|
|
725
|
+
engine: "ice",
|
|
726
|
+
database: "top",
|
|
727
|
+
schemaPath: ["does_not_exist"],
|
|
728
|
+
},
|
|
729
|
+
},
|
|
730
|
+
});
|
|
731
|
+
// The result is unchanged: nested namespace stays unresolved and the
|
|
732
|
+
// database keeps its two schemas (schemaless + nested).
|
|
733
|
+
const newDb = newState.connectionsMap
|
|
734
|
+
.get("ice" as ConnectionName)
|
|
735
|
+
?.databases.find((d) => d.name === "top");
|
|
736
|
+
expect(findSchema(newState, ["nested"])?.child_schemas_resolved).toBe(
|
|
737
|
+
false,
|
|
738
|
+
);
|
|
739
|
+
expect(newDb?.schemas.length).toBe(2);
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
describe("allTablesAtom with nested namespaces", () => {
|
|
744
|
+
it("enumerates tables from nested namespaces", () => {
|
|
745
|
+
const table = (name: string): DataTable => ({
|
|
746
|
+
name,
|
|
747
|
+
columns: [],
|
|
748
|
+
num_columns: 0,
|
|
749
|
+
num_rows: 0,
|
|
750
|
+
variable_name: null,
|
|
751
|
+
source: "iceberg",
|
|
752
|
+
source_type: "catalog",
|
|
753
|
+
type: "table",
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
const state = addConnection(
|
|
757
|
+
[
|
|
758
|
+
{
|
|
759
|
+
name: "ice" as ConnectionName,
|
|
760
|
+
source: "iceberg",
|
|
761
|
+
display_name: "Iceberg",
|
|
762
|
+
dialect: "iceberg",
|
|
763
|
+
databases: [
|
|
764
|
+
{
|
|
765
|
+
name: "top",
|
|
766
|
+
dialect: "iceberg",
|
|
767
|
+
schemas_resolved: true,
|
|
768
|
+
schemas: [
|
|
769
|
+
{
|
|
770
|
+
name: "",
|
|
771
|
+
tables: [table("toptable")],
|
|
772
|
+
tables_resolved: true,
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
name: "nested",
|
|
776
|
+
tables: [table("nestedtable")],
|
|
777
|
+
tables_resolved: true,
|
|
778
|
+
child_schemas_resolved: true,
|
|
779
|
+
child_schemas: [
|
|
780
|
+
{
|
|
781
|
+
name: "deep",
|
|
782
|
+
tables: [table("deeptable")],
|
|
783
|
+
tables_resolved: true,
|
|
784
|
+
child_schemas: [],
|
|
785
|
+
child_schemas_resolved: true,
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
},
|
|
789
|
+
],
|
|
790
|
+
},
|
|
791
|
+
],
|
|
792
|
+
},
|
|
793
|
+
],
|
|
794
|
+
initialState(),
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
store.set(dataSourceConnectionsAtom, state);
|
|
798
|
+
const names = [...store.get(allTablesAtom).values()].map((t) => t.name);
|
|
799
|
+
expect(names).toContain("toptable");
|
|
800
|
+
expect(names).toContain("nestedtable");
|
|
801
|
+
expect(names).toContain("deeptable");
|
|
802
|
+
});
|
|
803
|
+
});
|
|
@@ -49,6 +49,9 @@ export interface DataSourceState {
|
|
|
49
49
|
export interface SQLSchemaContext {
|
|
50
50
|
engine: string;
|
|
51
51
|
database: string;
|
|
52
|
+
// Parent schema path (relative to `database`) for nested schemas.
|
|
53
|
+
// Empty/undefined for the database's top level.
|
|
54
|
+
schemaPath?: string[];
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
export interface SQLTableContext {
|
|
@@ -58,6 +61,49 @@ export interface SQLTableContext {
|
|
|
58
61
|
dialect: string;
|
|
59
62
|
defaultSchema?: string | null;
|
|
60
63
|
defaultDatabase?: string | null;
|
|
64
|
+
// Nested schema path (relative to `database`). Empty/undefined at top level.
|
|
65
|
+
schemaPath?: string[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Immutably descend `path` (schema segment names) into a nested schema list
|
|
70
|
+
* and apply `update` to the matching schema. Unmatched branches are unchanged.
|
|
71
|
+
*/
|
|
72
|
+
function updateSchemaAtPath(
|
|
73
|
+
schemas: DatabaseSchema[],
|
|
74
|
+
path: string[],
|
|
75
|
+
update: (schema: DatabaseSchema) => DatabaseSchema,
|
|
76
|
+
): DatabaseSchema[] {
|
|
77
|
+
if (path.length === 0) {
|
|
78
|
+
return schemas;
|
|
79
|
+
}
|
|
80
|
+
const [head, ...rest] = path;
|
|
81
|
+
return schemas.map((schema) => {
|
|
82
|
+
if (schema.name !== head) {
|
|
83
|
+
return schema;
|
|
84
|
+
}
|
|
85
|
+
if (rest.length === 0) {
|
|
86
|
+
return update(schema);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
...schema,
|
|
90
|
+
child_schemas: updateSchemaAtPath(
|
|
91
|
+
schema.child_schemas ?? [],
|
|
92
|
+
rest,
|
|
93
|
+
update,
|
|
94
|
+
),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The path (schema/namespace segment names within a database) that locates the
|
|
101
|
+
* schema holding a set of tables. For nested namespaces this is the
|
|
102
|
+
* `schemaPath`; otherwise it is the single (possibly schemaless) schema name.
|
|
103
|
+
*/
|
|
104
|
+
function tableSchemaPath(sqlTableContext: SQLTableContext): string[] {
|
|
105
|
+
const { schemaPath, schema } = sqlTableContext;
|
|
106
|
+
return schemaPath && schemaPath.length > 0 ? schemaPath : [schema];
|
|
61
107
|
}
|
|
62
108
|
|
|
63
109
|
function initialState(): DataSourceState {
|
|
@@ -159,6 +205,7 @@ const {
|
|
|
159
205
|
return state;
|
|
160
206
|
}
|
|
161
207
|
|
|
208
|
+
const schemaPath = sqlSchemaContext.schemaPath ?? [];
|
|
162
209
|
const newMap = new Map(connectionsMap);
|
|
163
210
|
const newConn: DataSourceConnection = {
|
|
164
211
|
...conn,
|
|
@@ -166,10 +213,22 @@ const {
|
|
|
166
213
|
if (db.name !== sqlSchemaContext.database) {
|
|
167
214
|
return db;
|
|
168
215
|
}
|
|
216
|
+
// Top level: replace the database's schemas.
|
|
217
|
+
if (schemaPath.length === 0) {
|
|
218
|
+
return {
|
|
219
|
+
...db,
|
|
220
|
+
schemas: schemas,
|
|
221
|
+
schemas_resolved: true,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
// Nested namespace: replace the child schemas of the namespace at path.
|
|
169
225
|
return {
|
|
170
226
|
...db,
|
|
171
|
-
schemas: schemas,
|
|
172
|
-
|
|
227
|
+
schemas: updateSchemaAtPath(db.schemas, schemaPath, (schema) => ({
|
|
228
|
+
...schema,
|
|
229
|
+
child_schemas: schemas,
|
|
230
|
+
child_schemas_resolved: true,
|
|
231
|
+
})),
|
|
173
232
|
};
|
|
174
233
|
}),
|
|
175
234
|
};
|
|
@@ -198,6 +257,7 @@ const {
|
|
|
198
257
|
return state;
|
|
199
258
|
}
|
|
200
259
|
|
|
260
|
+
const path = tableSchemaPath(sqlTableContext);
|
|
201
261
|
const newMap = new Map(connectionsMap);
|
|
202
262
|
const newConn: DataSourceConnection = {
|
|
203
263
|
...conn,
|
|
@@ -207,16 +267,11 @@ const {
|
|
|
207
267
|
}
|
|
208
268
|
return {
|
|
209
269
|
...db,
|
|
210
|
-
schemas: db.schemas
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
...schema,
|
|
216
|
-
tables: tables,
|
|
217
|
-
tables_resolved: true,
|
|
218
|
-
};
|
|
219
|
-
}),
|
|
270
|
+
schemas: updateSchemaAtPath(db.schemas, path, (schema) => ({
|
|
271
|
+
...schema,
|
|
272
|
+
tables: tables,
|
|
273
|
+
tables_resolved: true,
|
|
274
|
+
})),
|
|
220
275
|
};
|
|
221
276
|
}),
|
|
222
277
|
};
|
|
@@ -246,6 +301,7 @@ const {
|
|
|
246
301
|
return state;
|
|
247
302
|
}
|
|
248
303
|
|
|
304
|
+
const path = tableSchemaPath(sqlTableContext);
|
|
249
305
|
const newMap = new Map(connectionsMap);
|
|
250
306
|
const newConn: DataSourceConnection = {
|
|
251
307
|
...conn,
|
|
@@ -253,21 +309,15 @@ const {
|
|
|
253
309
|
if (db.name !== sqlTableContext.database) {
|
|
254
310
|
return db;
|
|
255
311
|
}
|
|
256
|
-
|
|
257
312
|
return {
|
|
258
313
|
...db,
|
|
259
|
-
schemas: db.schemas
|
|
260
|
-
if (schema.name !== sqlTableContext.schema) {
|
|
261
|
-
return schema;
|
|
262
|
-
}
|
|
263
|
-
|
|
314
|
+
schemas: updateSchemaAtPath(db.schemas, path, (schema) => {
|
|
264
315
|
// If tables array is empty, add the table
|
|
265
316
|
// Otherwise, replace existing table or keep unchanged tables
|
|
266
317
|
const tables =
|
|
267
318
|
schema.tables.length === 0
|
|
268
319
|
? [table]
|
|
269
320
|
: schema.tables.map((t) => (t.name === tableName ? table : t));
|
|
270
|
-
|
|
271
321
|
return {
|
|
272
322
|
...schema,
|
|
273
323
|
tables,
|
|
@@ -327,9 +377,14 @@ export const allTablesAtom = atom((get) => {
|
|
|
327
377
|
const isDefaultDb =
|
|
328
378
|
database.name === conn.default_database || conn.databases.length === 1;
|
|
329
379
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
380
|
+
// Walk schemas recursively so nested namespaces (e.g. Iceberg
|
|
381
|
+
// `top.nested`) are enumerated. `segments` is the path of named
|
|
382
|
+
// (non-schemaless) namespace segments down to this schema.
|
|
383
|
+
const walkSchema = (schema: DatabaseSchema, segments: string[]): void => {
|
|
384
|
+
const schemalessDb = segments.length === 0;
|
|
385
|
+
const isDefaultSchema =
|
|
386
|
+
segments.length === 1 && segments[0] === conn.default_schema;
|
|
387
|
+
const schemaQualifier = segments.join(".");
|
|
333
388
|
|
|
334
389
|
for (const table of schema.tables) {
|
|
335
390
|
let nameToSave: string;
|
|
@@ -358,14 +413,14 @@ export const allTablesAtom = atom((get) => {
|
|
|
358
413
|
continue;
|
|
359
414
|
}
|
|
360
415
|
|
|
361
|
-
nameToSave = `${
|
|
416
|
+
nameToSave = `${schemaQualifier}.${table.name}`;
|
|
362
417
|
|
|
363
418
|
if (isDefaultDb && !tableNames.has(nameToSave)) {
|
|
364
419
|
tableNames.set(nameToSave, table);
|
|
365
420
|
continue;
|
|
366
421
|
}
|
|
367
422
|
|
|
368
|
-
nameToSave = `${database.name}.${
|
|
423
|
+
nameToSave = `${database.name}.${schemaQualifier}.${table.name}`;
|
|
369
424
|
|
|
370
425
|
if (tableNames.has(nameToSave)) {
|
|
371
426
|
Logger.warn(`Table name collision for ${nameToSave}. Skipping.`);
|
|
@@ -373,6 +428,15 @@ export const allTablesAtom = atom((get) => {
|
|
|
373
428
|
tableNames.set(nameToSave, table);
|
|
374
429
|
}
|
|
375
430
|
}
|
|
431
|
+
|
|
432
|
+
// Recurse into nested child namespaces. Children are always named.
|
|
433
|
+
for (const child of schema.child_schemas ?? []) {
|
|
434
|
+
walkSchema(child, [...segments, child.name]);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
for (const schema of database.schemas) {
|
|
439
|
+
walkSchema(schema, isSchemaless(schema.name) ? [] : [schema.name]);
|
|
376
440
|
}
|
|
377
441
|
}
|
|
378
442
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as I}from"./chunk-LvLJmgfZ.js";import{u as F}from"./useEvent-D91BmmQi.js";import{t as H}from"./react-Bj1aDYRI.js";import{Br as J,D as R,Hr as M}from"./cells-DOA0Gew8.js";import{t as G}from"./compiler-runtime-B3qBwwSJ.js";import{c as K}from"./utils-CvI-39U6.js";import{t as U}from"./jsx-runtime-BqBOg78p.js";import{c as V,d as W,gt as X}from"./JsonOutput-DRNPZOvX.js";import{t as q}from"./tooltip-B_PkSKN3.js";import{r as D,t as A}from"./button-BbCh-29a.js";import{r as Y}from"./requests-DIwGYs0l.js";import{t as Z}from"./createLucideIcon-D5guW7EU.js";import{t as ee}from"./useLifecycle-DieWOfXE.js";import{t as te}from"./spinner-Bhir8k53.js";import{r as ae}from"./useTheme-CI2eq4XN.js";import{t as re}from"./copy-icon-BuRdHNPA.js";import{t as se}from"./context-QkTujrKn.js";import{i as oe}from"./numbers-DGxQfQ-A.js";import{n as ne}from"./html-to-image-CyAtzePO.js";import{o as ce}from"./focus-Ldqh99xE.js";var P=Z("square-plus",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M8 12h8",key:"1wcyev"}],["path",{d:"M12 8v8",key:"napkw2"}]]),L=G(),le=I(H(),1),s=I(U(),1);const ie=i=>{let e=(0,L.c)(53),{table:t,column:a,preview:r,onAddColumnChart:c,sqlTableContext:o}=i,{theme:u}=ae(),{previewDatasetColumn:l}=Y(),{locale:d}=se(),m;e[0]!==a.name||e[1]!==l||e[2]!==o||e[3]!==t.name||e[4]!==t.source||e[5]!==t.source_type?(m=()=>{l({source:t.source,tableName:t.name,columnName:a.name,sourceType:t.source_type,fullyQualifiedTableName:o?`${o.database}.${o.schema}.${t.name}`:t.name})},e[0]=a.name,e[1]=l,e[2]=o,e[3]=t.name,e[4]=t.source,e[5]=t.source_type,e[6]=m):m=e[6];let p=m,f;if(e[7]!==r||e[8]!==p||e[9]!==t.source_type?(f=()=>{r||t.source_type==="connection"||t.source_type==="catalog"||p()},e[7]=r,e[8]=p,e[9]=t.source_type,e[10]=f):f=e[10],ee(f),t.source_type==="connection"){let n=a.name,E=a.external_type,x;e[11]!==a.name||e[12]!==c||e[13]!==o||e[14]!==t?(x=D.stopPropagation(()=>{c(M({table:t,columnName:a.name,sqlTableContext:o}))}),e[11]=a.name,e[12]=c,e[13]=o,e[14]=t,e[15]=x):x=e[15];let C;e[16]===Symbol.for("react.memo_cache_sentinel")?(C=(0,s.jsx)(P,{className:"h-3 w-3 mr-1"}),e[16]=C):C=e[16];let h;e[17]===x?h=e[18]:(h=(0,s.jsxs)(A,{variant:"outline",size:"xs",onClick:x,children:[C," Add SQL cell"]}),e[17]=x,e[18]=h);let S;return e[19]!==a.external_type||e[20]!==a.name||e[21]!==h?(S=(0,s.jsxs)("span",{className:"text-xs text-muted-foreground gap-2 flex items-center justify-between pl-7",children:[n," (",E,")",h]}),e[19]=a.external_type,e[20]=a.name,e[21]=h,e[22]=S):S=e[22],S}if(t.source_type==="catalog"){let n;return e[23]!==a.external_type||e[24]!==a.name?(n=(0,s.jsxs)("span",{className:"text-xs text-muted-foreground gap-2 flex items-center justify-between pl-7",children:[a.name," (",a.external_type,")"]}),e[23]=a.external_type,e[24]=a.name,e[25]=n):n=e[25],n}if(!r){let n;return e[26]===Symbol.for("react.memo_cache_sentinel")?(n=(0,s.jsx)("span",{className:"text-xs text-muted-foreground",children:"Loading..."}),e[26]=n):n=e[26],n}let g;e[27]!==r.error||e[28]!==r.missing_packages||e[29]!==p?(g=r.error&&O({error:r.error,missingPackages:r.missing_packages,refetchPreview:p}),e[27]=r.error,e[28]=r.missing_packages,e[29]=p,e[30]=g):g=e[30];let y=g,_;e[31]!==a.type||e[32]!==d||e[33]!==r.stats?(_=r.stats&&Q({stats:r.stats,dataType:a.type,locale:d}),e[31]=a.type,e[32]=d,e[33]=r.stats,e[34]=_):_=e[34];let b=_,j;e[35]!==r.chart_spec||e[36]!==u?(j=r.chart_spec&&$(r.chart_spec,u),e[35]=r.chart_spec,e[36]=u,e[37]=j):j=e[37];let N=j,k;e[38]!==r.chart_code||e[39]!==t.source_type?(k=r.chart_code&&t.source_type==="local"&&(0,s.jsx)(B,{chartCode:r.chart_code}),e[38]=r.chart_code,e[39]=t.source_type,e[40]=k):k=e[40];let z=k,v;e[41]!==a.name||e[42]!==c||e[43]!==o||e[44]!==t?(v=t.source_type==="duckdb"&&(0,s.jsx)(q,{content:"Add SQL cell",delayDuration:400,children:(0,s.jsx)(A,{variant:"outline",size:"icon",className:"z-10 bg-background absolute right-1 -top-1",onClick:D.stopPropagation(()=>{c(M({table:t,columnName:a.name,sqlTableContext:o}))}),children:(0,s.jsx)(P,{className:"h-3 w-3"})})}),e[41]=a.name,e[42]=c,e[43]=o,e[44]=t,e[45]=v):v=e[45];let T=v;if(!y&&!b&&!N){let n;return e[46]===Symbol.for("react.memo_cache_sentinel")?(n=(0,s.jsx)("span",{className:"text-xs text-muted-foreground",children:"No data"}),e[46]=n):n=e[46],n}let w;return e[47]!==z||e[48]!==T||e[49]!==N||e[50]!==y||e[51]!==b?(w=(0,s.jsxs)(W,{children:[y,z,T,N,b]}),e[47]=z,e[48]=T,e[49]=N,e[50]=y,e[51]=b,e[52]=w):w=e[52],w};function O({error:i,missingPackages:e,refetchPreview:t}){return(0,s.jsxs)("div",{className:"text-xs text-muted-foreground p-2 border border-border rounded flex items-center justify-between",children:[(0,s.jsx)("span",{children:i}),e&&(0,s.jsx)(V,{packages:e,showMaxPackages:1,className:"w-32",onInstall:t})]})}function Q({stats:i,dataType:e,locale:t}){return(0,s.jsx)("div",{className:"gap-x-16 gap-y-1 grid grid-cols-2-fit border rounded p-2 empty:hidden",children:Object.entries(i).map(([a,r])=>r==null?null:(0,s.jsxs)("div",{className:"flex items-center gap-1 group",children:[(0,s.jsx)("span",{className:"text-xs min-w-[60px] capitalize",children:J(a,e)}),(0,s.jsx)("span",{className:"text-xs font-bold text-muted-foreground tracking-wide",children:oe(r,t)}),(0,s.jsx)(re,{className:"h-3 w-3 invisible group-hover:visible",value:String(r)})]},a))})}var me=(0,s.jsx)("div",{className:"flex justify-center",children:(0,s.jsx)(te,{className:"size-4"})});function $(i,e){let t=a=>({...a,background:"transparent",config:{...a.config,background:"transparent"}});return(0,s.jsx)(le.Suspense,{fallback:me,children:(0,s.jsx)(X,{"data-container-width":"container",spec:t(JSON.parse(i)),options:{theme:e==="dark"?"dark":"vox",height:100,width:"container",actions:!1,renderer:"canvas"}})})}const B=i=>{let e=(0,L.c)(10),{chartCode:t}=i,a=F(K),r=ce(),{createNewCell:c}=R(),o;e[0]!==a||e[1]!==c||e[2]!==r?(o=p=>{p.includes("alt")&&ne({autoInstantiate:a,createNewCell:c,fromCellId:r}),c({code:p,before:!1,cellId:r??"__end__"})},e[0]=a,e[1]=c,e[2]=r,e[3]=o):o=e[3];let u=o,l;e[4]!==t||e[5]!==u?(l=D.stopPropagation(()=>u(t)),e[4]=t,e[5]=u,e[6]=l):l=e[6];let d;e[7]===Symbol.for("react.memo_cache_sentinel")?(d=(0,s.jsx)(P,{className:"h-3 w-3"}),e[7]=d):d=e[7];let m;return e[8]===l?m=e[9]:(m=(0,s.jsx)(q,{content:"Add chart to notebook",delayDuration:400,children:(0,s.jsx)(A,{variant:"outline",size:"icon",className:"z-10 bg-background absolute right-1 -top-0.5",onClick:l,children:d})}),e[8]=l,e[9]=m),m};export{Q as a,O as i,ie as n,P as o,$ as r,B as t};
|