const SIMPLE_LOWER_IDENTIFIER = /^[a-z_][a-z0-9_$]*$/; // PostgreSQL pg_get_keywords() categories R and T. GaussDB's PostgreSQL- // compatible modes use the same identifier constraints for bare names. const POSTGRES_RESERVED_IDENTIFIER_KEYWORDS = new Set([ "all", "analyse", "analyze", "and", "any", "array", "as", "asc", "asymmetric", "authorization", "binary", "both", "case", "cast", "check", "collate", "collation", "column", "concurrently", "constraint", "create", "cross", "current_catalog", "current_date", "current_role", "current_schema", "current_time", "current_timestamp", "current_user", "default", "deferrable", "desc", "distinct", "do", "else", "end", "except", "false", "fetch", "for", "foreign", "freeze", "from", "full", "grant", "group", "having", "ilike", "in", "initially", "inner", "intersect", "into", "is", "isnull", "join", "lateral", "leading", "left", "like", "limit", "localtime", "localtimestamp", "natural", "not", "notnull", "null", "offset", "on", "only", "or", "order", "outer", "overlaps", "placing", "primary", "references", "returning", "right", "select", "session_user", "similar", "some", "symmetric", "system_user", "table", "tablesample", "then", "to", "trailing", "true", "union", "unique", "user", "using", "variadic", "verbose", "when", "where", "window", "with", ]); // GaussDB MySQL-compatible drivers report a backtick. These additional words // cover MySQL-only names that cannot safely be emitted as bare identifiers. const MYSQL_ONLY_RESERVED_IDENTIFIER_KEYWORDS = new Set([ "accessible", "auto_increment", "change", "database", "databases", "delayed", "describe", "div", "dual", "enclosed", "escaped", "explain", "force", "fulltext", "high_priority", "ignore", "index", "infile", "key", "keys", "kill", "linear", "lines", "load", "lock", "low_priority", "master_ssl_verify_server_cert", "maxvalue", "mediumint", "mod", "no_write_to_binlog", "optimize", "optionally", "outfile", "partition", "purge", "range", "read_write", "regexp", "release", "rename", "replace", "require", "rlike", "schema", "schemas", "separator", "show", "spatial", "sql_big_result", "sql_calc_found_rows", "sql_small_result", "ssl", "starting", "straight_join", "terminated", "tinyint", "unlock", "unsigned", "use", "utc_date", "utc_time", "utc_timestamp", "values", "varbinary", "varchar", "write", "xor", "zerofill", ]); export function isExplicitlyQuotedSqlIdentifier(value: string): boolean { if (value.length < 2) return false; return (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("`") && value.endsWith("`")) || (value.startsWith("[") && value.endsWith("]")); } export function requiresPostgresIdentifierQuote(identifier: string, additionalKeywords?: ReadonlySet): boolean { if (!SIMPLE_LOWER_IDENTIFIER.test(identifier)) return true; return POSTGRES_RESERVED_IDENTIFIER_KEYWORDS.has(identifier) || additionalKeywords?.has(identifier) === true; } export function quoteGaussDbJdbcIdentifier(identifier: string, identifierQuote: string): string { if (isExplicitlyQuotedSqlIdentifier(identifier)) return identifier; const quote = identifierQuote.trim(); if (!quote) return identifier; const requiresQuote = !SIMPLE_LOWER_IDENTIFIER.test(identifier) || POSTGRES_RESERVED_IDENTIFIER_KEYWORDS.has(identifier) || (quote === "`" && MYSQL_ONLY_RESERVED_IDENTIFIER_KEYWORDS.has(identifier)); if (!requiresQuote) return identifier; return `${quote}${identifier.replaceAll(quote, quote + quote)}${quote}`; }