I have come across this same situation and it seems there are not many solutions around.
It seems putting order
and orderby
into the query parameter list places them as string literals like order by "name" "desc"
which reverts back to order by id asc
because they are now not descriptors. @gordon-linoff 's answer seems nice but I guess it still falls into the same trap for $1.
The following solution first uses string literals to build "order" query string then adds "where", "limit" and "offset" by parameters. However, it requires the developer to know what tables/columns are available and also which ones will be ordered (ordering some columns is meaningless).
let params = { page: 3, limit: 10, orderby: "name", order: "ASC" };
let orderby = ["id", "name", "family", "age"].includes(params.orderby)
? params.orderby
: "id";
let order = ["ASC", "DESC"].includes(params.order.toUpperCase())
? params.order
: "ASC";
client.query(
`SELECT name, family, age \
FROM customers \
WHERE id=$1 \
ORDER BY ${orderby} ${order} \
LIMIT $2 \
OFFSET $3`,
[id, params.limit, params.page]
);
EDIT: "string literals" are an ES6+ feature. for older JS versions, you can just use string concatenation by addition symbol: w="world"; str="hello" + w
PS: you can get column names before making the final string, but requires an extra connection to the database. though, you may place this in the initialization steps. check this answer for quick how-to: https://dba.stackexchange.com/a/22368/150156