fix(tdengine): display timezone timestamps and tags correctly

This commit is contained in:
zipg authored and GitHub committed 2026-08-22 19:17:05 +08:00
1 parent 2fee435b33
commit 36c9500a4e
9 files changed
+177 -40

No files matched your search

@@ -159,7 +159,7 @@ function bytesFromBufferLikeObject(value: unknown): Uint8Array | null {
return bytesFromByteArray(data);
}
export function parseBinaryCellBytes(value: unknown, columnType?: string): Uint8Array | null {
export function parseBinaryCellBytes(value: unknown, columnType?: string, databaseType?: DatabaseType): Uint8Array | null {
if (typeof value === "string") {
const prefixed = parseBinaryCellHexValue(value);
if (prefixed) return prefixed;
@@ -169,7 +169,7 @@ export function parseBinaryCellBytes(value: unknown, columnType?: string): Uint8
return bytesFromHex(trimmed.replace(/\\x/gi, ""));
}
if (isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) {
if (databaseType !== "tdengine" && isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) {
return bytesFromHex(trimmed);
}
}
@@ -189,16 +189,16 @@ export function canImportBinaryCellFile(databaseType?: DatabaseType, columnType?
return false;
}
export function canDownloadBinaryCellValue(value: unknown, columnType?: string): boolean {
return !!parseBinaryCellBytes(value, columnType);
export function canDownloadBinaryCellValue(value: unknown, columnType?: string, databaseType?: DatabaseType): boolean {
return !!parseBinaryCellBytes(value, columnType, databaseType);
}
export function binaryCellDisplayText(value: unknown, columnType?: string, originalBytes?: number): string | null {
export function binaryCellDisplayText(value: unknown, columnType?: string, originalBytes?: number, databaseType?: DatabaseType): string | null {
if (typeof value === "string" && isBinaryCellColumnType(columnType) && TRUNCATED_HEX_VALUE_RE.test(value.trim())) {
const size = originalBytes === undefined ? "..." : formatBinaryCellByteSize(originalBytes);
return `${binaryCellDisplayLabel(columnType)} [${size}]`;
}
const bytes = parseBinaryCellBytes(value, columnType);
const bytes = parseBinaryCellBytes(value, columnType, databaseType);
if (!bytes || !isBinaryCellColumnType(columnType)) return null;
if (BINARY_STRING_TYPE_RE.test((columnType ?? "").trim())) {
const previewBytes = FIXED_BINARY_TYPE_RE.test((columnType ?? "").trim()) ? trimTrailingNullBytes(bytes) : bytes;
@@ -245,8 +245,8 @@ export function formatBinaryCellByteSize(bytes: number): string {
return `${(bytes / (1024 * 1024)).toFixed(bytes < 10 * 1024 * 1024 ? 1 : 0)} MB`;
}
export function binaryCellDownloadPayload(value: unknown, mode: BinaryCellDownloadMode, columnType?: string): BinaryCellDownloadPayload {
const bytes = parseBinaryCellBytes(value, columnType);
export function binaryCellDownloadPayload(value: unknown, mode: BinaryCellDownloadMode, columnType?: string, databaseType?: DatabaseType): BinaryCellDownloadPayload {
const bytes = parseBinaryCellBytes(value, columnType, databaseType);
if (!bytes) {
throw new Error("Cell value is not a downloadable binary value.");
}
+10 -6
View File
@@ -1,5 +1,6 @@
import type { CellValue } from "@/lib/dataGrid/cellValue";
import { isBinaryCellColumnType, parseBinaryCellBytes } from "@/lib/dataGrid/binaryCellDownload";
import type { DatabaseType } from "@/types/database";
const IMAGE_PATH_RE = /\.(?:png|jpe?g|webp|gif|avif|bmp|svg)$/i;
const SAFE_DATA_IMAGE_RE = /^data:image\/(?:png|jpe?g|webp|gif|avif|bmp);base64,[a-z0-9+/=\s]+$/i;
@@ -14,10 +15,11 @@ function isLocalHttpHost(hostname: string): boolean {
export interface CellImagePreviewOptions {
binary?: boolean;
databaseType?: DatabaseType;
}
export function cellImagePreviewUrl(value: CellValue | unknown, columnType?: string, options: CellImagePreviewOptions = {}): string | null {
const binaryPreviewUrl = options.binary === false ? null : binaryImagePreviewUrl(value, columnType);
const binaryPreviewUrl = options.binary === false ? null : binaryImagePreviewUrl(value, columnType, options.databaseType);
if (binaryPreviewUrl) return binaryPreviewUrl;
if (typeof value !== "string") return null;
@@ -38,16 +40,16 @@ export function cellImagePreviewUrl(value: CellValue | unknown, columnType?: str
return text;
}
function binaryImagePreviewUrl(value: unknown, columnType?: string): string | null {
if (estimatedBinaryByteLength(value, columnType) > MAX_BINARY_IMAGE_PREVIEW_BYTES) return null;
const bytes = parseBinaryCellBytes(value, columnType);
function binaryImagePreviewUrl(value: unknown, columnType?: string, databaseType?: DatabaseType): string | null {
if (estimatedBinaryByteLength(value, columnType, databaseType) > MAX_BINARY_IMAGE_PREVIEW_BYTES) return null;
const bytes = parseBinaryCellBytes(value, columnType, databaseType);
if (!bytes || bytes.length > MAX_BINARY_IMAGE_PREVIEW_BYTES) return null;
const mimeType = detectImageMimeType(bytes);
if (!mimeType) return null;
return `data:${mimeType};base64,${bytesToBase64(bytes)}`;
}
function estimatedBinaryByteLength(value: unknown, columnType?: string): number {
function estimatedBinaryByteLength(value: unknown, columnType?: string, databaseType?: DatabaseType): number {
if (Array.isArray(value)) return value.length;
if (value && typeof value === "object" && Array.isArray((value as { data?: unknown }).data)) {
return (value as { data: unknown[] }).data.length;
@@ -58,7 +60,9 @@ function estimatedBinaryByteLength(value: unknown, columnType?: string): number
const prefixed = trimmed.match(HEX_PREFIX_RE);
if (prefixed) return prefixed[1].replace(/\s+/g, "").length / 2;
if (HEX_ESCAPE_RE.test(trimmed)) return trimmed.replace(/\s+/g, "").replace(/\\x/gi, "").length / 2;
if (isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) return trimmed.replace(/\s+/g, "").length / 2;
if (databaseType !== "tdengine" && isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) {
return trimmed.replace(/\s+/g, "").length / 2;
}
return 0;
}
@@ -1,6 +1,7 @@
import { cellImagePreviewUrl } from "@/lib/dataGrid/cellImageUrl";
import { displayCellValue, type CellValue } from "@/lib/dataGrid/cellValue";
import { formatJsonText } from "@/lib/dataGrid/cellDetailPresentation";
import type { DatabaseType } from "@/types/database";
export const CELL_DETAIL_VALUE_PREVIEW_MAX_LENGTH = 12_000;
@@ -48,6 +49,7 @@ export interface BuildDataGridCellDetailOptions {
commentByColumn?: ReadonlyMap<string, string>;
displayValue: (value: CellValue, columnIndex: number) => string;
isEditable: boolean;
databaseType?: DatabaseType;
includeBinaryImagePreview?: boolean;
isValuePreviewTruncated?: boolean;
}
@@ -109,7 +111,10 @@ export function buildDataGridCellDetail(options: BuildDataGridCellDetailOptions)
displayValue,
displayValuePreview,
isValuePreviewTruncated: options.isValuePreviewTruncated === true || rawValuePreview.length < rawValue.length || displayValuePreview.length < displayValue.length,
imagePreviewUrl: cellImagePreviewUrl(value, type, { binary: options.includeBinaryImagePreview !== false }),
imagePreviewUrl: cellImagePreviewUrl(value, type, {
binary: options.includeBinaryImagePreview !== false,
databaseType: options.databaseType,
}),
length: value === null ? 0 : String(value).length,
formattedJson,
isEditable: options.isEditable,