tediousjs / node-mssql

Microsoft SQL Server client for Node.js
https://tediousjs.github.io/node-mssql
MIT License
2.24k stars 471 forks source link

WHERE conditions on Object Catalog Views produce empty record sets #1574

Closed xchatzip closed 1 year ago

xchatzip commented 1 year ago

Using the latest version of the node-mssql library, I am unable to effectively query the object catalog views of my SQL Server Instance. In more detail, queries such as:

SELECT * FROM sys.objects

work perfecly, whereas queries such as:

SELECT * FROM sys.objects WHERE object_id = 113656444

produce empty record sets, despite the object_id existing in the aforementioned View. This I have ensured using multiple database clients, accessing the SQL server instance. Also, the same behaviour occurs in queries to the INFORMATION_SCHEMA, similar to:

SELECT * FROM INFORMATION_SCHEMA.COLUMNS c WHERE TABLE_SCHEMA = 'dbo'

Things I have already checked

Expected behaviour:

A non-empty resultset should have been returned.

Actual behaviour:

This was the result:

{
  recordsets: [ [] ],
  recordset: [],
  output: {},
  rowsAffected: [ 0 ],
  returnValue: 0
}

Code Example

I have created a minified example exposing the problem, using the code provided in the mssql npm documentation. It is important to note that when running this example, no error is returned

require("dotenv").config()
const sql = require('mssql')

const config = {
    user: process.env.DB_USER,
    password: process.env.DB_PWD,
    database: process.env.DB_NAME,
    server: process.env.DB_SERV,
    trustServerCertificate: true,
    pool: {
        max: 10,
        min: 0,
        idleTimeoutMillis: 30000
    }
}

async function fetchObj() {
    const pool = await new sql.ConnectionPool(config).connect()
    const ps = new sql.PreparedStatement(pool)
    ps.input('p0', sql.Int)
    ps.prepare('select * from sys.objects where object_id = @p0', err => {
        console.error(err)
        ps.execute({p0: 113656444}, (err, result) => {
            console.error(err)
            console.log(result)
            ps.unprepare(err => {
                console.error(err)
            })
        })
    })
}

fetchObj()

Software versions

dhensby commented 1 year ago

I've tried to replicate this locally and it works as expected for me.

Both using your example code (but with an object_id that exists in my database) and with my own code.

Here's an example (which runs successfully, it seems you don't have an object in your database with object ID 113656444):

const sql = require('mssql');
const pool = new sql.ConnectionPool({...});

(async () => {
  // connect to the database
  await pool.connect();
  // query the object ids that exist in the database
  const objects = await pool.query('SELECT object_id from sys.objects');
  // if there are not records, throw an error - we should have results!
  if (!objects.recordset.length) {
    throw new Error('No records returned');
  }
  // query each object by ID to ensure they can be returned
  const results = await Promise.all(objects.recordset.map(({ object_id }) => {
    return pool.query`SELECT * FROM sys.objects WHERE object_id = ${object_id}`;
  }));
  // loop over the entire set of returned rows and ensure they have a value
  results.forEach((row) => {
    if (!row.recordset.length) {
      throw new Error('Queried row did not return a value');
    }
  });
  console.log('All good');
})().catch(console.error).then(() => pool.close());