Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query function is actually called 3 times in express #57

Open
ghost opened this issue Apr 12, 2019 · 7 comments
Open

Query function is actually called 3 times in express #57

ghost opened this issue Apr 12, 2019 · 7 comments

Comments

@ghost
Copy link

ghost commented Apr 12, 2019

Hi there,

I've a weird issue there :

router.get("/list/", async (req, res, next) => {
  let promise = new Promise(function(resolve, reject) {
      db.query(queries.LIST, parameters, (err, rows, moreResultSets) => {
        if (err) {
          reject(err);
        } else {
          resolve(rows);
        }
      });
    });
    let result = await promise;
    res.status(200).send(result);
  });

The db.query function is somehow called 2 times and I don't know why exactly.

The first time it return an empty array, the second time the good one.

I'm using Express and it causes a lot of issues with res.send.

Thanks for the help 👍

@ghost ghost changed the title db.query called 2 times in express query function is actually called 2 times in express Apr 12, 2019
@ghost ghost changed the title query function is actually called 2 times in express db.query function is actually called 2 times in express Apr 12, 2019
@asztal
Copy link

asztal commented Apr 12, 2019

What is the query like? What database engine?

In my experience, a query like the following will generate two result sets with SQL Server:

select @someID = id from SomeTable where someColumn = 'someValue';

select id, value, foo, bar
from SomeOtherTable
where bazID = @someID;

The first result set has no row data but it does return a "rows affected" count. The same thing occurs if you insert into a temporary table or update/delete rows from a table.

And it is solved by prefixing the query with set rowcount off;.

@ghost
Copy link
Author

ghost commented Apr 13, 2019

What is the query like? What database engine?

In my experience, a query like the following will generate two result sets with SQL Server:

select @someID = id from SomeTable where someColumn = 'someValue';

select id, value, foo, bar
from SomeOtherTable
where bazID = @someID;

The first result set has no row data but it does return a "rows affected" count. The same thing occurs if you insert into a temporary table or update/delete rows from a table.

And it is solved by prefixing the query with set rowcount off;.

I'm calling a stored procedure on a Sybase Anywhere DB.

the db.query should only be called once and in express when I call the route I've got 2 different result (see the code above). Also it doesn't wait for the promise to be resolved (apparently).

The first time result is [] and the second time it got the rows.

So in Express it called the res.send with the empty array and doesn't send the one with the rows in it.

@ghost ghost changed the title db.query function is actually called 2 times in express query function is actually called 2 times in express Apr 13, 2019
@ghost
Copy link
Author

ghost commented Apr 15, 2019

Here is a full example (still using Sybase Anywhere 9 DB).

Query (queries.LIST)

SELECT *
FROM dba.xxx
WHERE id = ?

Code

router.get("/list/", (req, res, next) => {
  try {
    ...
    const parameters = [userId];
    db.query(queries.LIST, parameters, (err, rows, moreResultSets) => {
      if (err) {
        return res.status(400).json({ error: `an error occured: ${err}` });
      }
      console.log(rows);
      return res.status(200).send(rows);
    });
  } catch (e) {
    next(e);
  }
});

Result

[]
[]
 [ { lib: 'xxx', val: '111' },
   { lib: 'xxx', val: '222' } ]

It's called 3 times! I only call the route '/list' once.

It actually only res.send the first empty row and then :

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

@ghost ghost changed the title query function is actually called 2 times in express query function is actually called 3 times instead of 1 Apr 15, 2019
@ghost ghost changed the title query function is actually called 3 times instead of 1 query function is actually called 3 times in express Apr 15, 2019
@wankdanker
Copy link
Owner

Check the value of moreResultSets. If it is true, then the callback function is going to be called again. My guess is that it is true two times and then on the last time it is false. If that is the case, then for some reason, your database is returning empty result sets before the actual result set you are looking for.

You could then change your code to something like:

router.get("/list/", (req, res, next) => {
  try {
    ...
    const parameters = [userId];
    db.query(queries.LIST, parameters, (err, rows, moreResultSets) => {
      if (err) {
        return res.status(400).json({ error: `an error occured: ${err}` });
      }

      console.log(rows);

      if (!moreResultSets) { 
         return res.status(200).send(rows);
      }
    });
  } catch (e) {
    next(e);
  }
});

@ghost
Copy link
Author

ghost commented Apr 17, 2019

Check the value of moreResultSets. If it is true, then the callback function is going to be called again. My guess is that it is true two times and then on the last time it is false. If that is the case, then for some reason, your database is returning empty result sets before the actual result set you are looking for.

You could then change your code to something like:

router.get("/list/", (req, res, next) => {
  try {
    ...
    const parameters = [userId];
    db.query(queries.LIST, parameters, (err, rows, moreResultSets) => {
      if (err) {
        return res.status(400).json({ error: `an error occured: ${err}` });
      }

      console.log(rows);

      if (!moreResultSets) { 
         return res.status(200).send(rows);
      }
    });
  } catch (e) {
    next(e);
  }
});

Thanks, I'll try that.

Maybe the issue come from the stored procedure that's being called on the DB side (Sybase Anywhere 9).

I know I've received warnings (The result returned is non deterministic SQLCode=122) on InteractiveSQL.

Edit: Your code works with the query, thanks 👍

@ghost ghost changed the title query function is actually called 3 times in express Query function is actually called 3 times in express May 13, 2019
@ghost
Copy link
Author

ghost commented Jun 6, 2019

Hi there,

Is it possible to access somehow "moreResultsSets" with querySync ?

Thanks 👍

@kolzar
Copy link

kolzar commented Aug 31, 2020

What is the query like? What database engine?

In my experience, a query like the following will generate two result sets with SQL Server:

select @someID = id from SomeTable where someColumn = 'someValue';

select id, value, foo, bar
from SomeOtherTable
where bazID = @someID;

The first result set has no row data but it does return a "rows affected" count. The same thing occurs if you insert into a temporary table or update/delete rows from a table.

And it is solved by prefixing the query with set rowcount off;.

I think I have the same error. I am using nodejs & express on sql server.
I already tried as 'set rowcount 0' as 'set nocount off' without effect.
Any idea?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants