mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-29 16:18:55 +00:00
fix(export): page table data exports
This commit is contained in:
@@ -88,6 +88,7 @@ import {
|
||||
} from "@/lib/databaseCapabilities";
|
||||
import { sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick";
|
||||
import { formatCsv, formatJson, formatSqlInsert } from "@/lib/exportFormats";
|
||||
import { fetchTableDataForExport } from "@/lib/tableDataExport";
|
||||
import { buildCreateDatabaseSql, supportsCreateDatabaseCharset } from "@/lib/createDatabaseSql";
|
||||
import { buildRenameObjectSql, supportsObjectRename, type RenameableObjectType } from "@/lib/objectRenameSql";
|
||||
import { hexToRgba } from "@/lib/color";
|
||||
@@ -1061,29 +1062,30 @@ async function exportStructure() {
|
||||
async function exportData(format: "csv" | "json" | "sql") {
|
||||
const node = props.node;
|
||||
if (!node.connectionId || !node.database) return;
|
||||
const connectionId = node.connectionId;
|
||||
const database = node.database;
|
||||
const config = connectionStore.getConfig(node.connectionId);
|
||||
if (!config) return;
|
||||
|
||||
try {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
await connectionStore.ensureConnected(connectionId);
|
||||
const qualifiedName =
|
||||
isSchemaAware(config.db_type) && node.schema
|
||||
? `${quoteIdent(node.schema)}.${quoteIdent(node.label)}`
|
||||
: quoteIdent(node.label);
|
||||
const queryColumns =
|
||||
config.db_type === "neo4j"
|
||||
? (await api.getColumns(node.connectionId, node.database, node.schema || node.database, node.label)).map(
|
||||
? (await api.getColumns(connectionId, database, node.schema || database, node.label)).map(
|
||||
(column) => column.name,
|
||||
)
|
||||
: undefined;
|
||||
const dataSql = buildTableSelectSql({
|
||||
const result = await fetchTableDataForExport({
|
||||
databaseType: config.db_type,
|
||||
schema: node.schema,
|
||||
tableName: node.label,
|
||||
columns: queryColumns,
|
||||
limit: 10000,
|
||||
executePage: (sql) => api.executeQuery(connectionId, database, sql),
|
||||
});
|
||||
const result = await api.executeQuery(node.connectionId, node.database, dataSql);
|
||||
|
||||
let content: string;
|
||||
let ext: string;
|
||||
@@ -1100,7 +1102,7 @@ async function exportData(format: "csv" | "json" | "sql") {
|
||||
}
|
||||
|
||||
await saveFileContent(content, `${node.label}.${ext}`, ext.toUpperCase(), ext);
|
||||
toast(result.truncated ? t("grid.exported") + " (truncated)" : t("grid.exported"));
|
||||
toast(t("grid.exported"));
|
||||
} catch (e: any) {
|
||||
toast(t("grid.exportFailed", { message: e?.message || String(e) }), 5000);
|
||||
}
|
||||
@@ -1109,25 +1111,26 @@ async function exportData(format: "csv" | "json" | "sql") {
|
||||
async function exportDataXlsx() {
|
||||
const node = props.node;
|
||||
if (!node.connectionId || !node.database) return;
|
||||
const connectionId = node.connectionId;
|
||||
const database = node.database;
|
||||
const config = connectionStore.getConfig(node.connectionId);
|
||||
if (!config) return;
|
||||
|
||||
try {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
await connectionStore.ensureConnected(connectionId);
|
||||
const queryColumns =
|
||||
config.db_type === "neo4j"
|
||||
? (await api.getColumns(node.connectionId, node.database, node.schema || node.database, node.label)).map(
|
||||
? (await api.getColumns(connectionId, database, node.schema || database, node.label)).map(
|
||||
(column) => column.name,
|
||||
)
|
||||
: undefined;
|
||||
const dataSql = buildTableSelectSql({
|
||||
const result = await fetchTableDataForExport({
|
||||
databaseType: config.db_type,
|
||||
schema: node.schema,
|
||||
tableName: node.label,
|
||||
columns: queryColumns,
|
||||
limit: 10000,
|
||||
executePage: (sql) => api.executeQuery(connectionId, database, sql),
|
||||
});
|
||||
const result = await api.executeQuery(node.connectionId, node.database, dataSql);
|
||||
|
||||
const { buildXlsxWorkbook } = await import("@/lib/xlsxExport");
|
||||
const workbook = buildXlsxWorkbook({
|
||||
@@ -1136,7 +1139,7 @@ async function exportDataXlsx() {
|
||||
rows: result.rows,
|
||||
});
|
||||
await saveBinaryFileContent(workbook, `${node.label}.xlsx`, "Excel", "xlsx");
|
||||
toast(result.truncated ? t("grid.exported") + " (truncated)" : t("grid.exported"));
|
||||
toast(t("grid.exported"));
|
||||
} catch (e: any) {
|
||||
toast(t("grid.exportFailed", { message: e?.message || String(e) }), 5000);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { DatabaseType, QueryResult } from "../types/database.ts";
|
||||
import { buildTableSelectSql } from "./tableSelectSql.ts";
|
||||
|
||||
export const TABLE_DATA_EXPORT_PAGE_SIZE = 10_000;
|
||||
|
||||
export interface FetchTableDataForExportOptions {
|
||||
databaseType?: DatabaseType;
|
||||
schema?: string;
|
||||
tableName: string;
|
||||
columns?: string[];
|
||||
pageSize?: number;
|
||||
executePage: (sql: string) => Promise<QueryResult>;
|
||||
}
|
||||
|
||||
export async function fetchTableDataForExport(options: FetchTableDataForExportOptions): Promise<QueryResult> {
|
||||
const pageSize = Math.max(1, options.pageSize ?? TABLE_DATA_EXPORT_PAGE_SIZE);
|
||||
let offset = 0;
|
||||
const rows: QueryResult["rows"] = [];
|
||||
let columns: string[] = [];
|
||||
let executionTimeMs = 0;
|
||||
|
||||
while (true) {
|
||||
const sql = buildTableSelectSql({
|
||||
databaseType: options.databaseType,
|
||||
schema: options.schema,
|
||||
tableName: options.tableName,
|
||||
columns: options.columns,
|
||||
limit: pageSize,
|
||||
offset,
|
||||
});
|
||||
const result = await options.executePage(sql);
|
||||
if (columns.length === 0) columns = result.columns;
|
||||
rows.push(...result.rows);
|
||||
executionTimeMs += result.execution_time_ms ?? 0;
|
||||
|
||||
if (result.rows.length < pageSize) {
|
||||
return {
|
||||
columns,
|
||||
rows,
|
||||
affected_rows: 0,
|
||||
execution_time_ms: executionTimeMs,
|
||||
truncated: false,
|
||||
session_id: undefined,
|
||||
has_more: false,
|
||||
};
|
||||
}
|
||||
|
||||
offset += result.rows.length;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user