Quote SQL Identifiers Safely

Quote table and column identifiers for PostgreSQL or MySQL, doubling embedded quote characters and rejecting invalid names.

TypescriptSecurity Boundaries

Code

snippet
export type SqlDialect = "postgres" | "mysql";

export function quoteIdentifier(
  identifier: string,
  dialect: SqlDialect = "postgres",
): string {
  if (typeof identifier !== "string" || identifier.length === 0) {
    throw new TypeError("identifier must be a non-empty string");
  }
  if (identifier.includes("\0")) {
    throw new RangeError("identifier must not contain NUL");
  }
  if (dialect !== "postgres" && dialect !== "mysql") {
    throw new RangeError("unsupported SQL dialect");
  }
  const quote = dialect === "mysql" ? "`" : '"';
  return quote + identifier.split(quote).join(quote + quote) + quote;
}

export function qualifyTable(
  schema: string,
  table: string,
  dialect: SqlDialect = "postgres",
): string {
  return quoteIdentifier(schema, dialect) + "." + quoteIdentifier(table, dialect);
}