diff --git a/apps/desktop/src/lib/__tests__/codemirrorSqlDialect.spec.ts b/apps/desktop/src/lib/__tests__/codemirrorSqlDialect.spec.ts new file mode 100644 index 000000000..36cef6652 --- /dev/null +++ b/apps/desktop/src/lib/__tests__/codemirrorSqlDialect.spec.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from "vitest"; +import { PostgreSQL } from "@codemirror/lang-sql"; +import { postgresKeywordSyntaxTerms } from "@/lib/codemirrorSqlDialect"; + +describe("codemirrorSqlDialect", () => { + it("keeps common PostgreSQL identifier names out of keyword highlighting", () => { + const keywords = new Set(postgresKeywordSyntaxTerms(PostgreSQL.spec.keywords || "").split(/\s+/)); + + expect(keywords.has("select")).toBe(true); + expect(keywords.has("from")).toBe(true); + expect(keywords.has("where")).toBe(true); + expect(keywords.has("id")).toBe(false); + expect(keywords.has("name")).toBe(false); + expect(keywords.has("user")).toBe(false); + expect(keywords.has("count")).toBe(false); + }); +}); diff --git a/apps/desktop/src/lib/codemirrorSqlDialect.ts b/apps/desktop/src/lib/codemirrorSqlDialect.ts index 08fb55f84..265db5739 100644 --- a/apps/desktop/src/lib/codemirrorSqlDialect.ts +++ b/apps/desktop/src/lib/codemirrorSqlDialect.ts @@ -40,18 +40,27 @@ const DBX_COMMON_SQL_KEYWORDS = [ const POSTGRES_PLPGSQL_KEYWORDS = "PERFORM"; const POSTGRES_PLPGSQL_TYPES = "RECORD JSON JSONB"; const POSTGRES_PLPGSQL_BUILTIN = "SQLERRM TG_NAME TG_WHEN TG_LEVEL TG_OP TG_RELID TG_RELNAME TG_TABLE_NAME TG_TABLE_SCHEMA TG_NARGS TG_ARGV"; +const POSTGRES_IDENTIFIER_LIKE_KEYWORDS = new Set("COMMENT COUNT DATA DAY HOUR ID KEY LEVEL MINUTE MONTH NAME OWNER PASSWORD POSITION ROLE SECOND TYPE USER VALUE YEAR".split(" ")); // SQL Server table-valued parameters require READONLY in procedure/function declarations. const SQLSERVER_KEYWORDS = "readonly"; +export function postgresKeywordSyntaxTerms(keywords: string): string { + return keywords + .split(/\s+/) + .filter((keyword) => keyword && !POSTGRES_IDENTIFIER_LIKE_KEYWORDS.has(keyword.toUpperCase())) + .join(" "); +} + export function createDbxCodeMirrorSqlDialect(langSql: CodeMirrorSqlLanguageModule, dialectName: CodeMirrorSqlDialectName = "mysql"): SQLDialect { const baseDialect = dialectName === "postgres" ? langSql.PostgreSQL : dialectName === "sqlserver" ? langSql.MSSQL : langSql.MySQL; const isPostgres = dialectName === "postgres"; const isSqlServer = dialectName === "sqlserver"; + const baseKeywords = isPostgres ? postgresKeywordSyntaxTerms(baseDialect.spec.keywords || "") : baseDialect.spec.keywords || ""; return langSql.SQLDialect.define({ ...baseDialect.spec, - keywords: [baseDialect.spec.keywords || "", DBX_COMMON_SQL_KEYWORDS, isPostgres ? POSTGRES_PLPGSQL_KEYWORDS : "", isSqlServer ? SQLSERVER_KEYWORDS : ""].filter(Boolean).join(" "), + keywords: [baseKeywords, DBX_COMMON_SQL_KEYWORDS, isPostgres ? POSTGRES_PLPGSQL_KEYWORDS : "", isSqlServer ? SQLSERVER_KEYWORDS : ""].filter(Boolean).join(" "), types: [baseDialect.spec.types || "", isPostgres ? POSTGRES_PLPGSQL_TYPES : ""].filter(Boolean).join(" ") || undefined, builtin: [baseDialect.spec.builtin || "", isPostgres ? POSTGRES_PLPGSQL_BUILTIN : ""].filter(Boolean).join(" ") || undefined, doubleDollarQuotedStrings: false,