const query = `select foo from bar where zed = ${param}`; // forgot the sql tag
await runQuery(query);
In that case, the type of query is just string, but the `runQuery` method doesn't take strings, it takes a parsed query, so that wouldn't work.After using the tagged template literal pattern for SQL queries exclusively for the past couple years, I can't say enough how awesome it is to use in practice. Libraries even let you do strong typing with TypeScript to define the expected structure of the result, e.g.
sql<MyExpectedReturnType>`select foo from bar where zed = ${param}`The tagged template does not return a string in this case?
query = sql`select foo from bar where zed = ${p} order by ${col} asc`;
Unless the lib implements a real SQL parser for the right dialect, it will quote each expression in the same way, and will either fail or produce a broken SQL.The example you gave actually isn't valid, because what you're doing is generating SQL dynamically, and that doesn't work the way prepared statements work. That is, you can't have a prepared statement like "select foo from bar where zed = ? order by ? asc", because with prepared statements the question marks can only substitute for VALUES, not schema names. So if you wanted to do something like that it slonik, it would fail. With slonik you CAN do dynamic SQL, that is guaranteed to be safe and checked at compile time with TypeScript, because you can nest SQL tagged templates. That is you can do this:
const colToSortBy = useFoo ? sql`foo` : sql`bar`;
const query = sql`select col from mytable order by ${colToSortBy}`;
In that case slonik will know how to safely "merge" the parent and child parsed SQL.https://github.com/arangodb/arangojs/blob/main/src/aql.ts#L1...
Basically the `aql` template tag returns an object that can also be fed back into it and we also deduplicate arguments to avoid sending redundant data over the wire. There's also an escape hatch via a helper function (`aql.literal`) in cases where you need to insert literals that aren't known at compile time (e.g. you load query filters from a configuration file).
Tagged template strings are an absolutely brilliant feature and have tons of valuable uses. In particular, many sql libraries in node let you do this:
From a developer standpoint it "feels" just like you're doing string concatenation, but in reality the query variable will contain a prepared statement so that it safely prevents any kind of SQL injection, e.g. it gets parsed to There are lots of use cases where things are easily expressed as an interpolated string, but the thing you want back is NOT just a plain string, and tagged template literals are great for that. It's also a nice way to call a parser, e.g. many GraphQL libraries let you do: