mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-30 00:19:35 +00:00
349 lines
7.5 KiB
TypeScript
349 lines
7.5 KiB
TypeScript
import type { ColumnInfo, DatabaseType, IndexInfo } from "../types/database.ts";
|
|
import type { EditableStructureColumn, EditableStructureIndex } from "./tableStructureEditorSql.ts";
|
|
|
|
export const DATA_TYPE_OPTIONS: Record<string, string[]> = {
|
|
mysql: [
|
|
"tinyint",
|
|
"smallint",
|
|
"mediumint",
|
|
"int",
|
|
"integer",
|
|
"bigint",
|
|
"float",
|
|
"double",
|
|
"double precision",
|
|
"real",
|
|
"decimal",
|
|
"numeric",
|
|
"bit",
|
|
"boolean",
|
|
"bool",
|
|
"serial",
|
|
"char",
|
|
"varchar",
|
|
"tinytext",
|
|
"text",
|
|
"mediumtext",
|
|
"longtext",
|
|
"binary",
|
|
"varbinary",
|
|
"tinyblob",
|
|
"blob",
|
|
"mediumblob",
|
|
"longblob",
|
|
"enum",
|
|
"set",
|
|
"date",
|
|
"datetime",
|
|
"timestamp",
|
|
"time",
|
|
"year",
|
|
"json",
|
|
"geometry",
|
|
"point",
|
|
"linestring",
|
|
"polygon",
|
|
"multipoint",
|
|
"multilinestring",
|
|
"multipolygon",
|
|
"geometrycollection",
|
|
],
|
|
postgres: [
|
|
"smallint",
|
|
"int2",
|
|
"integer",
|
|
"int",
|
|
"int4",
|
|
"bigint",
|
|
"int8",
|
|
"smallserial",
|
|
"serial",
|
|
"bigserial",
|
|
"decimal",
|
|
"numeric",
|
|
"real",
|
|
"float",
|
|
"float4",
|
|
"double precision",
|
|
"float8",
|
|
"money",
|
|
"boolean",
|
|
"bool",
|
|
"char",
|
|
"character",
|
|
"varchar",
|
|
"character varying",
|
|
"text",
|
|
"bytea",
|
|
"date",
|
|
"time",
|
|
"time without time zone",
|
|
"time with time zone",
|
|
"timetz",
|
|
"timestamp",
|
|
"timestamp without time zone",
|
|
"timestamp with time zone",
|
|
"timestamptz",
|
|
"interval",
|
|
"uuid",
|
|
"json",
|
|
"jsonb",
|
|
"xml",
|
|
"bit",
|
|
"bit varying",
|
|
"varbit",
|
|
"tsvector",
|
|
"tsquery",
|
|
"cidr",
|
|
"inet",
|
|
"macaddr",
|
|
"macaddr8",
|
|
"point",
|
|
"line",
|
|
"lseg",
|
|
"box",
|
|
"path",
|
|
"polygon",
|
|
"circle",
|
|
"int4range",
|
|
"int8range",
|
|
"numrange",
|
|
"tsrange",
|
|
"tstzrange",
|
|
"daterange",
|
|
"oid",
|
|
],
|
|
sqlite: ["integer", "real", "text", "blob", "numeric"],
|
|
sqlserver: [
|
|
"bit",
|
|
"tinyint",
|
|
"smallint",
|
|
"int",
|
|
"integer",
|
|
"bigint",
|
|
"decimal",
|
|
"numeric",
|
|
"float",
|
|
"real",
|
|
"money",
|
|
"smallmoney",
|
|
"char",
|
|
"nchar",
|
|
"varchar",
|
|
"nvarchar",
|
|
"text",
|
|
"ntext",
|
|
"date",
|
|
"time",
|
|
"datetime",
|
|
"datetime2",
|
|
"smalldatetime",
|
|
"datetimeoffset",
|
|
"timestamp",
|
|
"binary",
|
|
"varbinary",
|
|
"image",
|
|
"uniqueidentifier",
|
|
"xml",
|
|
"sql_variant",
|
|
"hierarchyid",
|
|
"geography",
|
|
"geometry",
|
|
],
|
|
oracle: [
|
|
"number",
|
|
"integer",
|
|
"float",
|
|
"binary_float",
|
|
"binary_double",
|
|
"char",
|
|
"nchar",
|
|
"varchar2",
|
|
"nvarchar2",
|
|
"clob",
|
|
"nclob",
|
|
"long",
|
|
"date",
|
|
"timestamp",
|
|
"timestamp with time zone",
|
|
"timestamp with local time zone",
|
|
"interval year to month",
|
|
"interval day to second",
|
|
"raw",
|
|
"long raw",
|
|
"blob",
|
|
"bfile",
|
|
"boolean",
|
|
"json",
|
|
"vector",
|
|
"rowid",
|
|
"urowid",
|
|
"xmltype",
|
|
"sdo_geometry",
|
|
],
|
|
clickhouse: [
|
|
"Int8",
|
|
"Int16",
|
|
"Int32",
|
|
"Int64",
|
|
"Int128",
|
|
"Int256",
|
|
"UInt8",
|
|
"UInt16",
|
|
"UInt32",
|
|
"UInt64",
|
|
"UInt128",
|
|
"UInt256",
|
|
"Float16",
|
|
"Float32",
|
|
"Float64",
|
|
"Decimal",
|
|
"Decimal32",
|
|
"Decimal64",
|
|
"Decimal128",
|
|
"Decimal256",
|
|
"Bool",
|
|
"String",
|
|
"FixedString",
|
|
"Date",
|
|
"Date32",
|
|
"DateTime",
|
|
"DateTime64",
|
|
"UUID",
|
|
"IPv4",
|
|
"IPv6",
|
|
"Enum8",
|
|
"Enum16",
|
|
"Array",
|
|
"Map",
|
|
"Tuple",
|
|
"Nested",
|
|
"Nullable",
|
|
"LowCardinality",
|
|
"SimpleAggregateFunction",
|
|
"AggregateFunction",
|
|
"Point",
|
|
"Ring",
|
|
"Polygon",
|
|
"MultiPolygon",
|
|
"JSON",
|
|
],
|
|
};
|
|
|
|
export function createColumnDrafts(columns: ColumnInfo[]): EditableStructureColumn[] {
|
|
return columns.map((column, index) => ({
|
|
id: `existing:${column.name}`,
|
|
name: column.name,
|
|
dataType: column.data_type,
|
|
isNullable: column.is_nullable,
|
|
defaultValue: column.column_default ?? "",
|
|
comment: column.comment ?? "",
|
|
isPrimaryKey: column.is_primary_key,
|
|
original: column,
|
|
originalPosition: index,
|
|
markedForDrop: false,
|
|
}));
|
|
}
|
|
|
|
export function createIndexDrafts(indexes: IndexInfo[]): EditableStructureIndex[] {
|
|
return indexes.map((index) => ({
|
|
id: `existing:${index.name}`,
|
|
name: index.name,
|
|
columns: [...index.columns],
|
|
isUnique: index.is_unique,
|
|
isPrimary: index.is_primary,
|
|
filter: index.filter ?? "",
|
|
indexType: index.index_type ?? "",
|
|
includedColumns: index.included_columns ? [...index.included_columns] : [],
|
|
comment: index.comment ?? "",
|
|
original: index,
|
|
markedForDrop: false,
|
|
}));
|
|
}
|
|
|
|
export function toColumnNames(columns: string[]): string {
|
|
return columns.join(", ");
|
|
}
|
|
|
|
export function splitDataType(raw: string): { baseType: string; params: string } {
|
|
const trimmed = raw.trim();
|
|
const parenIdx = trimmed.indexOf("(");
|
|
if (parenIdx === -1) return { baseType: trimmed, params: "" };
|
|
const baseType = trimmed.slice(0, parenIdx).trim();
|
|
const params = trimmed.slice(parenIdx + 1, trimmed.lastIndexOf(")")).trim();
|
|
return { baseType, params };
|
|
}
|
|
|
|
export function combineDataType(baseType: string, params: string): string {
|
|
const type = baseType.trim();
|
|
const p = params.trim();
|
|
if (!type) return "";
|
|
if (!p) return type;
|
|
return `${type}(${p})`;
|
|
}
|
|
|
|
export function combineDataTypeForDatabase(dbType: DatabaseType | undefined, baseType: string, params: string): string {
|
|
return combineDataType(baseType, normalizeDataTypeParams(dbType, baseType, params));
|
|
}
|
|
|
|
export function normalizeDataTypeParams(dbType: DatabaseType | undefined, baseType: string, params: string): string {
|
|
const p = params.trim();
|
|
if (!p) return "";
|
|
if (!isTemporalPrecisionType(dbType, baseType)) return p;
|
|
return isValidTemporalPrecision(dbType, p) ? p : "";
|
|
}
|
|
|
|
function isTemporalPrecisionType(dbType: DatabaseType | undefined, baseType: string): boolean {
|
|
const normalized = baseType.trim().replace(/\s+/g, " ").toLowerCase();
|
|
switch (dbType) {
|
|
case "mysql":
|
|
case "doris":
|
|
case "starrocks":
|
|
case "goldendb":
|
|
case "sundb":
|
|
return ["time", "datetime", "timestamp"].includes(normalized);
|
|
case "postgres":
|
|
case "gaussdb":
|
|
case "opengauss":
|
|
case "highgo":
|
|
case "vastbase":
|
|
case "kingbase":
|
|
case "redshift":
|
|
return [
|
|
"time",
|
|
"time without time zone",
|
|
"time with time zone",
|
|
"timestamp",
|
|
"timestamp without time zone",
|
|
"timestamp with time zone",
|
|
].includes(normalized);
|
|
case "sqlserver":
|
|
return ["time", "datetime2", "datetimeoffset"].includes(normalized);
|
|
case "oracle":
|
|
case "dameng":
|
|
case "oceanbase-oracle":
|
|
return ["timestamp", "timestamp with time zone", "timestamp with local time zone"].includes(normalized);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function isValidTemporalPrecision(dbType: DatabaseType | undefined, params: string): boolean {
|
|
if (!/^\d+$/.test(params)) return false;
|
|
const value = Number(params);
|
|
const max = dbType === "oracle" || dbType === "dameng" || dbType === "oceanbase-oracle" ? 9 : 6;
|
|
return Number.isInteger(value) && value >= 0 && value <= max && String(value) === params;
|
|
}
|
|
|
|
export function buildStructureTargetLabel(
|
|
connectionName: string | undefined,
|
|
database: string | undefined,
|
|
schema: string | undefined,
|
|
tableName: string | undefined,
|
|
): string {
|
|
const parts = [connectionName, database];
|
|
if (schema && schema !== database) parts.push(schema);
|
|
if (tableName) parts.push(tableName);
|
|
return parts.filter(Boolean).join(" / ");
|
|
}
|