-
Notifications
You must be signed in to change notification settings - Fork 34
feat: views support #512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: views support #512
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -31,6 +31,7 @@ import { | |||
| setSectionExpanded, | ||||
| TABLES_GROUP_KEY, | ||||
| MATVIEWS_GROUP_KEY, | ||||
| VIEWS_GROUP_KEY, | ||||
| } from "../localStorageUtils" | ||||
| import { useSchema } from "../SchemaContext" | ||||
| import { QuestContext } from "../../../providers" | ||||
|
|
@@ -50,6 +51,7 @@ type VirtualTablesProps = { | |||
| tables: QuestDB.Table[] | ||||
| walTables?: QuestDB.WalTable[] | ||||
| materializedViews?: QuestDB.MaterializedView[] | ||||
| views?: QuestDB.View[] | ||||
| filterSuspendedOnly: boolean | ||||
| state: State | ||||
| loadingError: ErrorResult | null | ||||
|
|
@@ -82,6 +84,7 @@ export type FlattenedTreeItem = { | |||
| table?: QuestDB.Table | ||||
| column?: TreeColumn | ||||
| matViewData?: QuestDB.MaterializedView | ||||
| viewData?: QuestDB.View | ||||
| walTableData?: QuestDB.WalTable | ||||
| parent?: string | ||||
| isExpanded?: boolean | ||||
|
|
@@ -155,6 +158,7 @@ const VirtualTables: FC<VirtualTablesProps> = ({ | |||
| tables, | ||||
| walTables, | ||||
| materializedViews, | ||||
| views, | ||||
| filterSuspendedOnly, | ||||
| state, | ||||
| loadingError, | ||||
|
|
@@ -181,7 +185,7 @@ const VirtualTables: FC<VirtualTablesProps> = ({ | |||
| const wrapperRef = useRef<HTMLDivElement>(null) | ||||
| useRetainLastFocus({ virtuosoRef, focusedIndex, setFocusedIndex, wrapperRef }) | ||||
|
|
||||
| const [regularTables, matViewTables] = useMemo(() => { | ||||
| const [regularTables, matViewTables, viewTables] = useMemo(() => { | ||||
| return tables | ||||
| .reduce( | ||||
| (acc, table: QuestDB.Table) => { | ||||
|
|
@@ -200,15 +204,19 @@ const VirtualTables: FC<VirtualTablesProps> = ({ | |||
| const shownIfFilteredWithQuery = tableNameMatches || columnMatches | ||||
|
|
||||
| if (shownIfFilteredSuspendedOnly && shownIfFilteredWithQuery) { | ||||
| acc[table.matView ? 1 : 0].push({ | ||||
| // Use table_type to categorize: 'T' = table, 'M' = matview, 'V' = view | ||||
| // Default to 'T' (table) for backward compatibility with older servers | ||||
| const tableType = table.table_type ?? "T" | ||||
| const categoryIndex = tableType === "M" ? 1 : tableType === "V" ? 2 : 0 | ||||
| acc[categoryIndex].push({ | ||||
| ...table, | ||||
| hasColumnMatches: columnMatches, | ||||
| }) | ||||
| return acc | ||||
| } | ||||
| return acc | ||||
| }, | ||||
| [[], []] as (QuestDB.Table & { hasColumnMatches: boolean })[][], | ||||
| [[], [], []] as (QuestDB.Table & { hasColumnMatches: boolean })[][], | ||||
| ) | ||||
| .map((tables) => | ||||
| tables.sort((a, b) => | ||||
|
|
@@ -224,23 +232,22 @@ const VirtualTables: FC<VirtualTablesProps> = ({ | |||
| }, [] as FlattenedTreeItem[]) | ||||
| }, [schemaTree]) | ||||
|
|
||||
| const handleCopyQuery = async (tableName: string, isMatView: boolean) => { | ||||
| const handleCopyQuery = async (tableName: string, kind: "table" | "matview" | "view") => { | ||||
| try { | ||||
| let response | ||||
| if (isMatView) { | ||||
| response = await quest.showMatViewDDL(tableName) | ||||
| } else { | ||||
| response = await quest.showTableDDL(tableName) | ||||
| } | ||||
| const response = | ||||
| kind === "matview" | ||||
| ? await quest.showMatViewDDL(tableName) | ||||
| : kind === "view" | ||||
| ? await quest.showViewDDL(tableName) | ||||
| : await quest.showTableDDL(tableName) | ||||
|
|
||||
| if (response?.type === QuestDB.Type.DQL && response.data?.[0]?.ddl) { | ||||
| await copyToClipboard(response.data[0].ddl) | ||||
| toast.success("Schema copied to clipboard") | ||||
| } | ||||
| } catch (error) { | ||||
| toast.error( | ||||
| `Cannot copy schema for ${isMatView ? "materialized view" : "table"} '${tableName}'`, | ||||
| ) | ||||
| const kindLabel = kind === "matview" ? "materialized view" : kind === "view" ? "view" : "table" | ||||
| toast.error(`Cannot copy schema for ${kindLabel} '${tableName}'`) | ||||
| } | ||||
| } | ||||
|
|
||||
|
|
@@ -474,18 +481,24 @@ const VirtualTables: FC<VirtualTablesProps> = ({ | |||
| ) | ||||
| } | ||||
|
|
||||
| if (item.id === TABLES_GROUP_KEY || item.id === MATVIEWS_GROUP_KEY) { | ||||
| if (item.id === TABLES_GROUP_KEY || item.id === MATVIEWS_GROUP_KEY || item.id === VIEWS_GROUP_KEY) { | ||||
| const isTable = item.id === TABLES_GROUP_KEY | ||||
| const isMatView = item.id === MATVIEWS_GROUP_KEY | ||||
| const isView = item.id === VIEWS_GROUP_KEY | ||||
|
||||
| const isView = item.id === VIEWS_GROUP_KEY |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type assertion might be unsafe here. The item.kind could theoretically be "view", but the SuspensionDialog is being passed item.kind as "table" | "matview" which excludes "view". While the code does check canSuspend before rendering the dialog (which ensures kind !== "view"), TypeScript doesn't recognize this relationship. Consider refactoring to make the type narrowing more explicit, or ensure SuspensionDialog can handle all valid kinds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Views are being filtered based on suspension status when
filterSuspendedOnlyis true. However, regular views typically don't have WAL support since they're virtual and cannot be suspended. This logic may incorrectly filter out views when the "Show suspended only" filter is active. Consider excluding views (table_type === 'V') from the suspension filter logic.