fix(mysql): handle binary hex display and empty values

This commit is contained in:
zipg authored and GitHub committed 2026-08-12 10:59:56 +08:00
1 parent 275b4d5831
commit 81f45ba048
4 files changed
+69 -28

No files matched your search

@@ -5036,7 +5036,6 @@ function primitiveCellFormatKey(value: CellValue, columnIndex?: number): string
function formatCell(value: CellValue, columnIndex?: number): string {
const formatter = columnIndex === undefined ? undefined : resolvedColumnFormatters.value[columnIndex];
const columnName = columnIndex === undefined ? undefined : props.result.columns[columnIndex];
const columnInfo = columnIndex === undefined ? undefined : tableColumnForGridColumn(columnIndex);
const displayColumnInfo = columnInfo ?? (columnIndex === undefined ? undefined : resultColumnInfoForGridColumn(columnIndex));
const arrayDisplay = formatter
@@ -5047,8 +5046,8 @@ function formatCell(value: CellValue, columnIndex?: number): string {
columnInfo: displayColumnInfo,
});
if (arrayDisplay !== undefined) return arrayDisplay;
const binaryDisplay = formatter ? null : binaryCellDisplayText(value, columnInfo?.data_type ?? (columnName ? columnTypeMap.value.get(columnName) : undefined));
if (binaryDisplay) return binaryDisplay;
const binaryDisplay = formatter ? null : binaryCellDisplayText(value, columnIndex === undefined ? undefined : allColumnTypes.value[columnIndex]);
if (binaryDisplay !== null) return binaryDisplay;
const s = applyColumnFormatter(value, formatter);
return limitDataGridCellDisplay(s, resolvedDatabaseType.value === "sqlserver" ? SQLSERVER_DATA_GRID_CELL_DISPLAY_MAX_LENGTH : undefined);
}
@@ -107,10 +107,12 @@ export function retainBinaryCellDownloadMenuForHover(openCell: BinaryCellPositio
return openCell?.rowIndex === hoveredCell.rowIndex && openCell.col === hoveredCell.col ? openCell : null;
}
const HEX_VALUE_RE = /^(?:0[xX]|\\x)([0-9a-fA-F\s]+)$/;
const HEX_VALUE_RE = /^(?:0[xX]|\\x)([0-9a-fA-F\s]*)$/;
const BARE_HEX_RE = /^[0-9a-fA-F\s]+$/;
const HEX_ESCAPE_RE = /^(?:\\x[0-9a-fA-F]{2}|\s)+$/;
const BINARY_TYPE_RE = /^(?:blob|tinyblob|mediumblob|longblob|bytea|bytes|binary|varbinary|image|raw|long\s+raw)(?:\b|\()/i;
const FIXED_BINARY_TYPE_RE = /^binary(?:\b|\()/i;
const BINARY_STRING_TYPE_RE = /^(?:binary|varbinary)(?:\b|\()/i;
const MYSQL_FILE_IMPORT_TYPE_RE = /^(?:blob|tinyblob|mediumblob|longblob|binary|varbinary)(?:\b|\()/i;
function copyBytesForBlob(bytes: Uint8Array): Uint8Array<ArrayBuffer> {
@@ -127,7 +129,8 @@ export function parseBinaryCellHexValue(value: CellValue): Uint8Array | null {
function bytesFromHex(value: string): Uint8Array | null {
const hex = value.replace(/\s+/g, "");
if (!hex || hex.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(hex)) return null;
if (hex.length === 0) return new Uint8Array();
if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(hex)) return null;
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
@@ -192,9 +195,35 @@ export function canDownloadBinaryCellValue(value: unknown, columnType?: string):
export function binaryCellDisplayText(value: unknown, columnType?: string): string | null {
const bytes = parseBinaryCellBytes(value, columnType);
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;
const text = printableUtf8Text(previewBytes);
if (text !== null) return text;
}
return `${binaryCellDisplayLabel(columnType)} [${formatBinaryCellByteSize(bytes.length)}]`;
}
function trimTrailingNullBytes(bytes: Uint8Array): Uint8Array {
let end = bytes.length;
while (end > 0 && bytes[end - 1] === 0) end--;
return bytes.subarray(0, end);
}
function printableUtf8Text(bytes: Uint8Array): string | null {
let text: string;
try {
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
} catch {
return null;
}
for (const char of text) {
const codePoint = char.codePointAt(0) ?? 0;
const allowedWhitespace = codePoint === 9 || codePoint === 10 || codePoint === 13;
if (!allowedWhitespace && (codePoint <= 31 || (codePoint >= 127 && codePoint <= 159))) return null;
}
return text;
}
function binaryCellDisplayLabel(columnType?: string): string {
const base = (columnType ?? "")
.trim()