node-postgres icon indicating copy to clipboard operation
node-postgres copied to clipboard

Parameters of type Set() not working

Open bf opened this issue 2 years ago • 1 comments

First of all, thanks for this great module.

I have noticed that Set() iterators are not working as params for node-postgres. Here a working example with latest version of node-postgres (v.8.9.0) on node.js v19.6.0.

  const databaseClient = await event.context.db.connect()

  const mySet = new Set()
  mySet.add(3427)
  mySet.add(3420)
  mySet.add(3421)
  mySet.add(3422)

  const sqlQuery = "SELECT * FROM filesystem WHERE id = ANY($1)"

  // FAILS with only `Set`
  const result1 = await databaseClient.query(sqlQuery, [ mySet ])
  console.log("result1.rows.length for", mySet, "has", result1.rows.length, "rows")

  // FAILS with `Set.values()`
  const result2 = await databaseClient.query(sqlQuery, [ mySet.values() ])
  console.log("result2.rows.length for", mySet.values(), "has", result2.rows.length, "rows")

  // WORKS with array
  let arr = []
  for (const val of mySet) {
    arr.push(val)
  }
  const result3 = await databaseClient.query(sqlQuery, [ arr ])
  console.log("result3.rows.length for", arr, "has", result3.rows.length, "rows")

  // WORKS with `Array.from(Set)`
  const result4 = await databaseClient.query(sqlQuery, [ Array.from(mySet) ])
  console.log("result4.rows.length for", Array.from(mySet), "has", result4.rows.length, "rows")

console output as follows (result should have 4 rows):

result1.rows.length for Set(4) { 3427, 3420, 3421, 3422 } has 0 rows
result2.rows.length for [Set Iterator] { 3427, 3420, 3421, 3422 } has 0 rows
result3.rows.length for [ 3427, 3420, 3421, 3422 ] has 4 rows
result4.rows.length for [ 3427, 3420, 3421, 3422 ] has 4 rows

logs from postgreSQL:

LOG:  execute <unnamed>: SELECT * FROM filesystem WHERE id = ANY($1)
DETAIL:  parameters: $1 = '{}'
LOG:  execute <unnamed>: SELECT * FROM filesystem WHERE id = ANY($1)
DETAIL:  parameters: $1 = '{}'
LOG:  execute <unnamed>: SELECT * FROM filesystem WHERE id = ANY($1)
DETAIL:  parameters: $1 = '{3427,3420,3421,3422}'
LOG:  execute <unnamed>: SELECT * FROM filesystem WHERE id = ANY($1)
DETAIL:  parameters: $1 = '{3427,3420,3421,3422}'

My suggestion is that Set or Set Iterator parameter types should be converted to array internally via `Array.from(<Set>)' .

bf avatar Feb 20 '23 14:02 bf

This might work: Set.prototype.toPostgres = function(prepareValue) { return prepareValue(Array.from(this)); }

kapouer avatar Sep 05 '23 10:09 kapouer