Home > Software engineering >  Why is my dynamic sql resulting in the error shown below?
Why is my dynamic sql resulting in the error shown below?

Time:01-29

I am trying to build a sql statement dynamically and this is one variation of the result.

sqlQuery {
  name: 'fetch-products',
  text: 'select * from products where category = 
  $1 and designer in $2',
  values: [ 'WOMENSCLOTHING', "('Adjavon', 'ALC', 'Adele', 'Bagley')" ]
}

I build the sql with the following code segment:

const {
    category,
    designers,
} = JSON.parse(filters);

let values = [category];

let text = 'select * from products where category = $1';

if(designers) {
    text = text   ' and designer in $2';
    values.push(designers);
}

I execute it in the following segment:

try {
    const allProducts = await pool.query(sqlQuery);

    res.status(200).json(allProducts.rows);
} catch (error) {
    console.error(error);
    return res.status(500).send('Problems gettting products by category.')
}

And get the following error:

error: syntax error at or near "$2"

I am thinking the error may be the double quotes placed around designer when it is pushed on the values array:

values: [ 'WOMENSCLOTHING', "('Adjavon', 'ALC', 'Adele', 'Bagley')" ]

CodePudding user response:

I don't know what library you are using exactly, but the values property looks highly suspicious.

sqlQuery {
  name: 'fetch-products',
  text: 'select * from products where category = 
  $1 and designer in $2',
  values: [ 'WOMENSCLOTHING', "('Adjavon', 'ALC', 'Adele', 'Bagley')" ]
}

If your drivr/library supports this, the second element in the array should be an actual array and not a string like '("foo", "bat")'. How is the driver supposed to know this is meant as a list and not a single string that has this value?

I guess in a nutshell you have to bring the query in this form:

const query = 'select * from products where category = $1 and designer in ($2, $3, $4, $5)'

const values =  [ 'WOMENSCLOTHING', 'Adjavon', 'ALC', 'Adele', 'Bagley' ]

That requires some extra work on the backend to map the values and bring them into the right shape.

I guess you could get that done with something like this:

const category = 'icecream'
const designers = ['jim', 'maria']

let values = [category];

let text = 'select * from products where category = $1';

if (designers) {
  text  = ` and designer in (${designers.map((d, i) => `$${i 2}`).join(', ')})`;
  values = [...values, ...designers];
}

console.log(text);
console.log(values);

  •  Tags:  
  • Related