'How can I bind a variable to sequelize literal?

I have this subquery that is used to check the existence of a column related to the source model.

const defaultingLoans = await Loan.findAll({
    where: {
      [Op.and]: database.sequelize.literal('EXISTS(SELECT * FROM "Instalments" WHERE "Instalments"."loanId" = "Loan"."id" AND "Instalments"."status" = 'pending')')
    }
  });

The query works fine but the value pending ideally won't be fixed so I'll like to have a variable there that can be used to query for different status.

How can I replace the pending string with a variable.

Concatenation didn't work here because Sequelize has a weird way of parsing concatenated SQL queries which result in an error. An example is here https://pastebin.com/u8tr4Xbt and I took a screenshot of the error here



Solution 1:[1]

You can turn defaultingLoans into a function which accepts an amount:

const defaultingLoans = amount => await Loan.findAll({
  where: {
    [Op.and]: database.sequelize.literal(`EXISTS(SELECT * FROM "Instalments" WHERE "Instalments"."loanId" = "Loan"."id" AND "Instalments"."amount" = ${amount})`)
  }
});

usage:

const loans = defaultingLoans(2000);

EDIT: Although it should be noted here that you need to sanitize or quote the amount getting passed into this function to avoid SQL injection attacks.

Solution 2:[2]

You can put your bind object right inside your query object:

let status = 'Pending';
const defaultingLoans = await Loan.findAll({
    where: database.sequelize.literal('EXISTS(SELECT * FROM "Instalments" WHERE "Instalments"."loanId" = "Loan"."id" AND "Instalments"."status" = $status)'),
    bind: {status}
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 BMiner
Solution 2 tlumko