Skip to main content

sql.raw(text)

ADVANCED - most users will not need this function.

DO NOT USE!

This function invites SQL injection vulnerabilities. There's almost always a better way.

Used for embedding raw SQL text directly into a query.

Syntax

sql.raw(text: string): SQL

Parameters

  • text - Raw SQL text to embed directly

Description

⚠️ EXTREME DANGER: YOU ARE INVITING SQL INJECTION

Embeds raw SQL with zero safety checks. This bypasses all SQL injection protections.

This is an escape hatch only. The number of valid use cases for this function are vanishingly small. In 99.9% of cases, there is a safer alternative using other pg-sql2 functions.

Safer alternatives

Use sql`...` , sql.identifier(), sql.value(), sql.literal() or any of the other sql.* methods instead.

// ❌ sql.raw(userInput) -> SQL injection!
// ✅ sql`ASC` for SQL text
// ✅ sql.identifier(tableName) for table/column names
// ✅ sql.value(userInput) for values
// ✅ sql.literal(50) for constants

Instead of reaching for sql.raw(), consider using composition: break complex SQL into small safe fragments that can be composed.

const COLUMNS = {
__proto__: null,
name: sql.identifier("users", "name"),
email: sql.identifier("users", "email"),
created_at: sql.identifier("users", "created_at"),
};

const DIRECTIONS = {
__proto__: null,
asc: sql.literal("ASC"),
desc: sql.literal("DESC"),
};

// Usage
const column = COLUMNS[userInputColumn] || COLUMNS["created_at"];
const direction = DIRECTIONS[userInputDirection] || DIRECTIONS["asc"];

const query = sql`SELECT * FROM users ORDER BY ${column} ${direction}`;

This approach ensures that only predefined, safe values are used.

Beware built-in properties

When using maps, be sure to use a null prototype so built-in properties can't be exploited.

Return value

Returns a SQL fragment containing the raw text that will be inserted verbatim into the compiled query.

When you might need this

Very rare cases where sql.raw() might be necessary:

  • Working with SQL that's generated by other trusted tools

Security checklist

Before using sql.raw(), verify ALL of these:

  • The text is deterministic
  • The text is only generated from expressions you control
  • User input will never be included in the text
  • The text is valid SQL that won't break the query
  • You understand the SQL injection risks
  • The text has been reviewed by a security-aware developer
  • You've considered and ruled out all safer alternatives
  • You've considered and ruled out all safer alternatives again, because it's really unlikely that you can't solve this a better way
  • You've worked with a colleague to consider safer alternatives and still ruled them all out
  • You've consulted with the Graphile Discord, and still no-one can suggest a safer alternative