From ca0d4356c0aed1f24b7a4b7f69c3a23d6537de8b Mon Sep 17 00:00:00 2001 From: Melody Ruch <396921921@qq.com> Date: Wed, 26 Aug 2026 13:51:51 +0800 Subject: [PATCH] fix(editor): highlight pg and mysql builtin functions --- .../editor/codemirrorSqlDialect.spec.ts | 10 ++++++ .../src/lib/editor/codemirrorSqlDialect.ts | 33 ++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/apps/desktop/src/lib/__tests__/editor/codemirrorSqlDialect.spec.ts b/apps/desktop/src/lib/__tests__/editor/codemirrorSqlDialect.spec.ts index 2b34a666c4..c83a001f56 100644 --- a/apps/desktop/src/lib/__tests__/editor/codemirrorSqlDialect.spec.ts +++ b/apps/desktop/src/lib/__tests__/editor/codemirrorSqlDialect.spec.ts @@ -16,6 +16,16 @@ describe("codemirrorSqlDialect", () => { expect(keywords.has("count")).toBe(false); }); + it("highlights common functions dropped from Postgres/MySQL keyword lists as builtins", () => { + const postgresBuiltins = new Set(createDbxCodeMirrorSqlDialect(langSql, "postgres", "postgres").spec.builtin?.split(/\s+/)); + const mysqlBuiltins = new Set(createDbxCodeMirrorSqlDialect(langSql, "mysql", "mysql").spec.builtin?.split(/\s+/)); + + expect(postgresBuiltins.has("count")).toBe(true); + expect(postgresBuiltins.has("to_char")).toBe(true); + expect(mysqlBuiltins.has("ifnull")).toBe(true); + expect(mysqlBuiltins.has("date_format")).toBe(true); + }); + it("adds Dolt routines to highlighting without changing standard MySQL", () => { const doltBuiltins = new Set(createDbxCodeMirrorSqlDialect(langSql, "mysql", "mysql", "dolt").spec.builtin?.split(/\s+/)); const mysqlBuiltins = new Set(createDbxCodeMirrorSqlDialect(langSql, "mysql", "mysql", "mysql").spec.builtin?.split(/\s+/)); diff --git a/apps/desktop/src/lib/editor/codemirrorSqlDialect.ts b/apps/desktop/src/lib/editor/codemirrorSqlDialect.ts index 4706ea841a..aa6f92a0e6 100644 --- a/apps/desktop/src/lib/editor/codemirrorSqlDialect.ts +++ b/apps/desktop/src/lib/editor/codemirrorSqlDialect.ts @@ -143,6 +143,36 @@ const CLICKHOUSE_TYPES = [ const CLICKHOUSE_BUILTINS = ["now", "today", "toDate", "toDateTime", "toDateTime64", "toYYYYMM", "count", "sum", "avg", "min", "max", "uniq", "uniqExact", "argMin", "argMax", "groupArray", "arrayJoin", "mapKeys", "mapValues", "JSONExtract", "JSONExtractString"].join(" ").toLowerCase(); +// COUNT is stripped from Postgres keywords by postgresKeywordSyntaxTerms() (it's a +// valid Postgres identifier name), so it's re-added here as a builtin function instead. +const POSTGRES_BUILTINS = [ + "count", + "coalesce", + "nullif", + "greatest", + "least", + "to_char", + "to_date", + "to_number", + "to_timestamp", + "extract", + "date_trunc", + "date_part", + "now", + "current_date", + "current_timestamp", + "array_agg", + "string_agg", + "lower", + "upper", + "length", + "substring", + "trim", + "concat", +].join(" "); + +const MYSQL_BUILTINS = ["ifnull", "date_format", "str_to_date", "date_add", "date_sub", "curdate", "curtime", "unix_timestamp", "from_unixtime", "group_concat", "concat_ws"].join(" "); + export function postgresKeywordSyntaxTerms(keywords: string): string { return keywords .split(/\s+/) @@ -179,6 +209,7 @@ function codeMirrorBaseDialect(langSql: CodeMirrorSqlLanguageModule, dialectName export function createDbxCodeMirrorSqlDialect(langSql: CodeMirrorSqlLanguageModule, dialectName: CodeMirrorSqlDialectName = "mysql", databaseType?: DatabaseType, driverProfile?: string): SQLDialect { const baseDialect = codeMirrorBaseDialect(langSql, dialectName, databaseType); const isPostgres = baseDialect === langSql.PostgreSQL; + const isMysql = baseDialect === langSql.MySQL; const isSqlServer = baseDialect === langSql.MSSQL; const isPlsql = baseDialect === langSql.PLSQL; const isClickHouse = databaseType === "clickhouse" || dialectName === "clickhouse"; @@ -190,7 +221,7 @@ export function createDbxCodeMirrorSqlDialect(langSql: CodeMirrorSqlLanguageModu ...baseDialect.spec, keywords: [baseKeywords, commonKeywords, isClickHouse ? CLICKHOUSE_KEYWORDS : "", isPostgres ? POSTGRES_PLPGSQL_KEYWORDS : "", isSqlServer ? SQLSERVER_KEYWORDS : ""].filter(Boolean).join(" "), types: [baseTypes, isClickHouse ? CLICKHOUSE_TYPES : "", isPostgres ? POSTGRES_PLPGSQL_TYPES : ""].filter(Boolean).join(" ") || undefined, - builtin: [baseDialect.spec.builtin || "", isClickHouse ? CLICKHOUSE_BUILTINS : "", isPostgres ? POSTGRES_PLPGSQL_BUILTIN : "", driverProfileSqlBuiltinTerms(driverProfile)].filter(Boolean).join(" ") || undefined, + builtin: [baseDialect.spec.builtin || "", isClickHouse ? CLICKHOUSE_BUILTINS : "", isPostgres ? `${POSTGRES_BUILTINS} ${POSTGRES_PLPGSQL_BUILTIN}` : "", isMysql ? MYSQL_BUILTINS : "", driverProfileSqlBuiltinTerms(driverProfile)].filter(Boolean).join(" ") || undefined, ...(isClickHouse ? { identifierQuotes: '"`',