javascriptnode.jstypescriptpostgresql

Problem with double quotes when creating an Enum


I'm using Postgres.js to build an application and I'm creating an Enum for user roles like the following

import { PostgresError } from 'postgres';
import sql from './database/index.js';


const RolesEnum = {
    user : 'user',
    moderator : 'moderator',
    admin : 'admin'
} as const;

const Enum = ['user', 'moderator', 'admin'] as const;

async function Build() {
    try {
        await sql`DROP TYPE F_that;`.catch(() => {}); // IF DOESN'T EXIST THEN PASS
        const { statement } = await sql`CREATE TYPE F_that AS ENUM (${sql(
            Enum
        )});`;
        console.log(statement);
    } catch (error) {
        console.error(
            (error as PostgresError).query ?? (error as Error).message ?? error
        );
        /* Logs the following
          CREATE TYPE F_that AS ENUM ( "user", "moderator" , "admin" );*/
    }
}

await Build() // Logs the following: CREATE TYPE F_that AS ENUM ( "user", "moderator" , "admin" );`

The problem is the double quotes in the Enum values, which gives an Error in Postgres. How to make them single quotes in the query?

The closest solution I got was adding this to the catch block:

if (error instanceof postgres.PostgresError) {
            error.query.replaceAll('"', "'"); // gets query with single quotes for the Enum
   }

which gives the right query but I can't use it like above (whenever I try to get an error about a positional parameter, I guess it runs at run time?)


Solution

  • Use sql.unsafe. This is safe because you're using a hardcoded array.

    await sql`DROP TYPE IF EXISTS F_that;`;
    
    # to escape single quotes if any
    const enumValues = Enum.map(v => `'${v.replace(/'/g, "''")}'`).join(', ');
    
    await sql`CREATE TYPE F_that AS ENUM (${sql.unsafe(enumValues)});`;