fix(oracle): copy temporal cells in display format

Closes #8569
This commit is contained in:
t8y2 committed 2026-09-09 13:13:09 +08:00
1 parent c63d7927f9
commit c8ef1f44f3
3 files changed
+44 -2

No files matched your search

@@ -7012,6 +7012,7 @@ const {
sourceColumns: visibleSourceColumns,
columnComments: visibleColumnComments,
allColumnComments,
displayValue: formatCellCached,
mongoDocuments: computed(() => props.result.mongo_copy_documents ?? props.result.mongo_documents),
spatialColumns: computed(() => props.result.spatial_columns),
spatialValues: computed(() => props.result.spatial_values),
@@ -1,10 +1,12 @@
import { computed, ref } from "vue";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { useDataGridExport, type UseDataGridExportOptions } from "@/composables/useDataGridExport";
import type { DatabaseType } from "@/types/database";
import { buildDataGridCopyUpdateStatements } from "@/lib/dataGrid/dataGridSql";
import { copyToClipboard } from "@/lib/common/clipboard";
import type { DataGridTableMeta } from "@/lib/dataGrid/dataGridSql";
import type { CellSelectionMatrix, SelectionData } from "@/lib/dataGrid/gridSelection";
import type { CellValue } from "@/lib/dataGrid/cellValue";
import { extractDataGridSelection } from "@/lib/backend/api";
import { DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS } from "@/lib/dataGrid/dataGridCopyExtractor";
import { clearDataGridClipboardCopy, parseDataGridClipboard } from "@/lib/dataGrid/dataGridClipboard";
@@ -115,6 +117,8 @@ function createExportState(
isSyntheticContext = false,
contextRowId?: number | null,
contextColumn?: number,
databaseType: DatabaseType = "mysql",
displayValue?: (value: CellValue, columnIndex: number) => string,
) {
const rows = (rowDataList ?? [rowData ?? columns.map((column, index) => (column === "id" ? 1 : `value-${index}`))]).map((data, index) => ({ ...row(data), id: index + 1 }));
const resolvedContextRowId = contextRowId === undefined ? (rows[0]?.id ?? null) : contextRowId;
@@ -124,7 +128,8 @@ function createExportState(
displayItems: computed(() => rows),
sql: computed(() => undefined),
tableMeta: computed(() => tableMeta),
databaseType: computed(() => "mysql"),
databaseType: computed(() => databaseType),
displayValue,
connectionId: computed(() => "connection-1"),
database: computed(() => "dbx"),
context: computed(() => "table-data"),
@@ -738,6 +743,35 @@ describe("useDataGridExport prepared row statements", () => {
expect(copyToClipboard).toHaveBeenCalledWith("");
});
it("copies Oracle temporal cells using the displayed value", async () => {
const table: DataGridTableMeta = {
tableName: "events",
columns: [{ name: "created_at", data_type: "timestamp", is_nullable: true }],
primaryKeys: [],
};
const state = createExportState(
table,
["created_at"],
undefined,
["2020-12-02T15:18:29"],
undefined,
undefined,
[],
DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS,
false,
undefined,
false,
1,
0,
"oracle",
() => "2020-12-02 15:18:29",
);
await state.copyCell();
expect(copyToClipboard).toHaveBeenCalledWith("2020-12-02 15:18:29");
});
it("copies all rows with empty fields for NULL cells", async () => {
const text = "id\tname\n1\t\n2\tAda";
const state = createExportState(editableTable, ["id", "name"], undefined, undefined, undefined, [
@@ -23,6 +23,7 @@ import { useSettingsStore } from "@/stores/settingsStore";
import { expandNestedJsonStringsForCopy } from "@/lib/common/jsonCopyValue";
import { buildMongoCopyDocumentFromOriginal, buildMongoCopyInsertDocument, buildMongoCopyUpdateDocument, formatMongoShellLiteral, type MongoInputValue } from "@/lib/mongo/mongoDocumentValues";
import { formatMongoShellText } from "@/lib/mongo/mongoFormatter";
import { isTemporalColumnType } from "@/lib/dataGrid/columnFormatter";
import type { DatabaseType, QueryResult } from "@/types/database";
import type { QueryResultExportRequest } from "@/lib/backend/api";
import { usesSyntheticRowIdKey } from "@/lib/table/tableEditing";
@@ -82,6 +83,7 @@ export interface UseDataGridExportOptions {
copyInsertTargetLabel?: ComputedRef<string | undefined>;
mongoUpdateTarget?: ComputedRef<MongoCopyUpdateTarget | undefined>;
databaseType: ComputedRef<DatabaseType | undefined>;
displayValue?: (value: CellValue, columnIndex: number) => string;
identifierQuote?: ComputedRef<string | undefined>;
connectionId: ComputedRef<string | undefined>;
database: ComputedRef<string | undefined>;
@@ -553,7 +555,12 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
const [resolvedItem] = await resolveVisibleRowValues([item], [sourceIndex]);
const val = resolvedItem?.data[contextCell.value.col] ?? null;
// 外部剪贴板呈现文本型 MySQL VARBINARY(NULL 也按空串输出);内部网格副本仍保留原 hex,保证回粘无损。
await copyText(clipboardCellValue(binaryClipboardCellValue(val, contextCell.value.col)), { rows: [[val]] });
const rawValue = clipboardCellValue(binaryClipboardCellValue(val, contextCell.value.col));
const copyValue =
options.databaseType.value === "oracle" && isTemporalColumnType(options.columnTypes.value?.[contextCell.value.col])
? options.displayValue?.(val, sourceIndex) ?? rawValue
: rawValue;
await copyText(copyValue, { rows: [[val]] });
}
async function copyRow() {