I'm using node.js 6.9.0 and "firebird": "^0.1.3" connecting to a firebird 3. Currently, I have several queries that are working perfectly just calling in the form 'select * from ...' then I decided to create a stored procedure and I'm having 2 problems.
The connexion.query is no longer an FBResult object(thenFunc) to apply the fetch that was giving me an error,
When I don't treat the result as an FBResult because is already a JSON string the received values are always null, However, I receive the correct column names.
The initial call was like this:
var sql = "EXECUTE PROCEDURE PRESENCE_GETTOTAL;"
var resultVec = [];
connexion.query(sql , function (err,rs){
if( rs == null && err != null ){
return reject(err);
}
else{
console.log(rs);
rs.fetch('all',true,function (rs){
ShopDayString.push(rs);
}, function (err, oef){
if(oef) resolve(ShopDayString);
if(err) reject(err);
});
Then I realized it was giving back in rs the result as a JSON so I change it this way:
var sql = "EXECUTE PROCEDURE PRESENCE_GETTOTAL;"
var resultVec = [];
console.log(sql)
connexion.query(sql , function (err,rs){
if ( rs == null && err != null ){
return reject(err);
}
else{
console.log(rs);
resultVec.push(rs);
resolve(resultVec)
}
});
The problem now is that the values are always null, I run the exact same command in the isql-fb client and I got results. Does anyone have any idea why this is happening?
The correct way to execute a stored procedure is like this:
var stmt = connexion.prepareSync("EXECUTE PROCEDURE PRESENCE_GETTOTAL;")
var res = stmt.execSync();
if(res){
resolve(res);
}
else{
res.fetch('all',true,function (rs){
resultVec.push(rs);
}, function (err, oef){
if(oef) resolve(resultVec);
if(err) reject(err);
});
}
So when we execute the Sync there is 2 option, If it is a single row it will immediately return the result. Otherwise, it will return undefined and you will have to fetch the results.
You can get more info in the library repository
edit 1: cleaner code suggested not using 'undefined'.
Related
I am new to node.js.
I am trying to create function, where a randomly generated String is queried to check if it exists or not. If it already exists, the String is randomly generated till it is unique.
let validID = false;
console.log(temp); //temp is the randomly generated String.
while(!validID){
Website.findOne({shortcut: temp},function(err,docs){
if(docs==null){
validID = true;
console.log("The shortcut for the url is" + temp);
}else{
console.log("FOUND");
temp = generateId();
}
});
}
When run, the code is stuck in an infinite while loop.
I tried to see whether the code works with a String value ( not a variable ) passed in as the query inside findOne(). It worked. I am assuming that the fact that temp is a variable is causing the problem. Can variables be passed in as a value in a query? If so, what is the correct way?
Website.findOne operates asynchronously, i.e. the callback-function you passed to it, will be run once the results from the mongodb are fetched. However, node will not be able to actually process this callback, since your callstack never gets emptied due to your while-loop. If you're interested, you can find out more about this here.
One way to solve this is to wrap your Mongo-DB call in a promise, wait for it to resolve, then return if the ID is unique and continue by calling it recursively otherwise (note that this can be highly simplified by using async/await but for understanding how this works using promised are beneficial imo):
function findIdPromise(temp) {
return new Promise((resolve, reject) => {
Website.findOne({
shortcut: temp
}, function (err, docs) {
if (err) {
return reject(err);
}
resolve(docs);
});
});
}
function getNextIsUniqueIdPromise(shortcut) {
return findIdPromise()
.then(docs => {
if (docs == null) {
return shortcut;
}
return getNextIsUniqueIdPromise(generateId());
});
}
// call it initially with
getNextIsUniqueIdPromise(firstShortcutToCheck)
.then(shortcut => {
console.log("The shortcut for the url is" + shortcut):
})
.catch(err => {
console.log("an error occured", err):
});
Hi Can anyone give an example of how use insert statement in nodejs. I am able to use select query. But for insert query i am getting the result as []. no error can be seen but the values are not added to the original table. I am using db2, ibm_db,express,nodejs and angularjs.
I wrote a blog entry on using DB2 and node.js on Bluemix a while ago. It includes code for an INSERT statement.
As part of the insert
first prepare the statement,
then bind the values to be inserted and
finally execute the statement.
Here is the relevant code snippet, the full context is in the blog:
exports.insertIP = function(ibmdb,connString,ipinfo) {
console.log("insertIP called",ipinfo);
ibmdb.open(connString, function(err, conn) {
if (err ) {
res.send("error occurred " + err.message);
}
else {
// prepare the SQL statement
conn.prepare("INSERT INTO IP.VISITORS(vtime,ip,country_code,country,region_code,region,city,zip,latitude,longitude,metro,area) VALUES (current timestamp,?,?,?,?,?,?,?,?,?,?,?)", function(err, stmt) {
if (err) {
//could not prepare for some reason
console.log(err);
return conn.closeSync();
}
//Bind and Execute the statment asynchronously
stmt.execute([ipinfo["ip"],ipinfo["country_code"],ipinfo["country_name"],ipinfo["region_code"],ipinfo["region_name"],ipinfo["city"],ipinfo["zipcode"], ipinfo["latitude"], ipinfo["longitude"],ipinfo["metro_code"],ipinfo["area_code"]], function (err, result) {
console.log(err);
// Close the connection to the database
conn.close(function(){
console.log("Connection Closed");
});
});
});
}
})};
I would suggest and recommend (as one of the members of node-ibm_db) to follow the node-ibm_db github repository (https://github.com/ibmdb/node-ibm_db) , we have updated the README document as well as the list of APIs to do particular tasks.
For your above query you can use ".prepare(sql, callback)" or ".prepareSync(sql)" API (as per your requirements Async/sync call), below is the attached code snippet and URL link for particular API documentation.
var ibmdb = require("ibm_db"),
cn ="DATABASE=dbname;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=dbuser;PWD=xxx";
ibmdb.open(cn,function(err,conn){
conn.prepare("insert into hits (col1, col2) VALUES (?, ?)",
function (err, stmt) {
if (err) {
//could not prepare for some reason
console.log(err);
return conn.closeSync();
}
//Bind and Execute the statment asynchronously
stmt.execute(['something', 42], function (err, result) {
if( err ) console.log(err);
else result.closeSync();
//Close the connection
conn.close(function(err){});
});
});
});
API documentation(Github URL) : https://github.com/ibmdb/node-ibm_db#-8-preparesql-callback
Try to install jt400 by using the below command
npm install node-jt400 --save
use the below code to insert the data to table name foo.
Follow link https://www.npmjs.com/package/node-jt400 for for details
pool
.insertAndGetId('INSERT INTO foo (bar, baz) VALUES(?,?)',[2,'b'])
.then(id => {
console.log('Inserted new row with id ' + id);
});
This node/express function is giving me an error:
Can't set headers after they are sent.
it used to work fine, but i have made some changes to the user schema, moving all address items to be under 'address', like this:
firstname,
lastname,
address:{
street,
city,
loc (array of numbers)
...
}
so the new function looks like this:
export function searchMembers(req, res) {
var lat = req.body.lat;
var lon = req.body.lon;
var zoom = req.body.zoom || 14;
var query = User.find();
var distance = 5000;
// when this line is removed, problem is gone:
query = query.where('address.loc').near({center:{type:'Point', coordinates:[lon,lat]}, maxDistance: distance, spherical:true});
query = query.where({'address.city': 'Toronto'});
query = query.sort({'lastname': 1});
query.exec(function(err,users){
if(err) res.send(err);
var final = [];
_.forEach(users, function(x){
var obj = {};
obj.id = x._id;
obj.name=x.firstname + ' ' + x.lastname;
obj.latitude=x.address.loc[1] ;
obj.longitude=x.address.loc[0] ;
final.push(obj);
});
res.status(200).json(final);
});
}
So when i run this, i get the funny error: Can't set headers after they are sent.
pointing to the last line in the function:
res.status(200).json(final);
i tried to eliminate stuff to find the root cause.
when i remove the where line with the 'near' function, the problem is gone.
i have added other filtering, just for testing, everything fine. only this one is causing an issue.
Any idea?
This error means, that you already used method res.json()/render()/send() and you try to do it again.
In your case, this line does not stop method from executing if(err) res.send(err);
You have to write return to stop it.
if(err) {
res.send(err);
return;
}
Which is equivalent to
if(err) {
return res.send(err);
}
Just do not think about it as returning "res.send(err)", it is using res.send(err) and after that using return to stop executing.
The reason why removing line also removes error :
You have some error in that line (like having bad column names), therefore in callback the error is send and then you use res.send(err) and after that you call res.status(200).json(final)
I've got a problem with javascript/node js functions.
When I send an sql query with function query of "request.service.mssql" object, the result function is called twice...
I don't understand because my sql query is an "update" and the result is empty (I do not have multiple lines of results)
For example, I have a function that send an email with a new password. The email is sent twice... I found a temp solution with an index but it's not very clean.
Can you explain this ?
//construct SQL query
var email = "test#toto.com";
var password = require("crypto").randomBytes(4).toString('hex');
var password_md5 = require("crypto").createHash("md5").update(password).digest("hex");
var sql = "update dbo.mytable SET password='"+password_md5+"' where id=12";
var id = 0; //temp solution
mssql.query(sql,
{
success: function(results) {
//Send email with new pwd
if(id == 0) {
response.send(statusCodes.OK,password_md5);
sendEmail(email,password);
}
id++; //temp solution
},
error: function(err) {
response.send(statusCodes.INTERNAL_SERVER_ERROR,"Error : " + err);
}
});
Thank you :-)
Steve
I get the answer on another forum : I have to prefix my SQL statement with set nocount on; command.
Thank you for your help.
Steve
I am using node.js with mongoose. The problem i am facing is i am getting newModifier1 printed but outside that function the value is null.
Here is my code:
// Find userSchema
newModifier1 = "";
exports.findModifier = function(modifierName){
modifierModel.find({'name' : modifierName},function(err,result){
if(err){
console.log("Error : "+err);
throw err;
}
else{
newModifier1 = result;
// console.log("Modifier is searched successfully : "+newModifier1);
}
console.log("Modifier is searched successfully1 : "+newModifier1);
});
// newModifier1=temp;
return newModifier1; // it takes newModifier1 = "" value here
}
Any ideas what the problem could be?
This is what is happening:
// this is "global" an would be weirdly overwritten
// if function is called multiple times before finishing
newModifier1 = "";
exports.findModifier = function(modifierName){
// TIMESTAMP: 0
modifierModel.find({'name' : modifierName},function(err,result){
// TIMESTAMP: 2
if(err){
console.log("Error : "+err);
throw err;
}
else{
newModifier1 = result;
// console.log("Modifier is searched successfully : "+newModifier1);
}
console.log("Modifier is searched successfully1 : "+newModifier1);
});
// TIMESTAMP: 1
return newModifier1; // it takes newModifier1 = "" value here
}
I added some notes, when what is happening. As you can see and because of the async nature of node.js you return the value before you get a result back from the database.
You need familiarize yourself with the async flow and callback function.
Pass a callback function to findModifier and wait for the database to return a result.
modifierModel.find runs asynchronously and probably findModifier method is returning before the callback of find method executes. Although you see it being printed out what is returned from the method is en empty string anyway. You can use a library like async.