I use MySQL in NodeJS to connect to the SQL Server. I use below code for get cities for example and I have a question, this is a correct way to close the connection after query has done?
I ask to be sure. thanks.
const getCities = async (req, resp) => {
try {
const { proId } = req.params;
await sql.connect(sqlConfig).then(async (pool) => {
return await pool
.request()
.input("proId", sql.BigInt, proId)
.execute("getCities")
.then((result) => {
resp.status(200).send(result.recordsets[0]);
})
.catch((err) => {
resp.status(500).send({ msg: serverError, err: err });
})
.finally(() => {
pool.close();
});
});
} catch (err) {
return resp.status(500).send({ msg: serverError, err: err });
}
};
because of this answer link we should not close pool after every request
Related
When i try to get result from node-postgres from my express app, pool.query is returning undefined result when i log it in console. Not sure if its about database connected properly or I am not returning the result properly? I am using heroku to deploy the app and using connection string given by heroku. Cant figure it out, anyone there to help please?.
db.js:
const { Pool } = require('pg');
const conString = process.env.DATABASE_URL;
const pool = new Pool({
connectionString: conString,
ssl: {rejectUnauthorized: false}
});
module.exports ={
getResult: (sql, params, callback)=>{
pool.query(sql, [params], (error, results)=>{
console.log(results);
if(!error){
callback(results);
}else{
callback(null);
}
pool.end();
});
}
}
user-model.js
var db = require('./db');
module.exports ={
findUserById: (userId)=>{
return new Promise((resolve, reject)=>{
var sql = "select id from users where id=?";
db.getResult(sql, [userId], (result)=>{
if(result.length>0){
resolve(true);
}else{
resolve(false);
}
});
});
}
}
seems the sent query parameter is in mysql format, use node-postgres format which is var sql = "select id from users where id = $1"; which should return valid result
It seems that your use of params is not correct.
You're passing an array to db.getResult(), then using it as the first element of another array.
Should just be pool.query(sql, params, (error, results)=>{ on that line.
you need to get the pool connection
const pool = require('./pool');
module.exports = {
// my version
findUserById(sql, params) {
return new Promise((resolve, reject) => {
return pool
.connect()
.then(conn => {
conn
.query(sql, [params])
.then(result => {
conn.release()
resolve(result)
})
.catch(error => {
conn.release()
reject(error)
})
})
})
},
// your version
findUserByIds: (userId) => {
return new Promise((resolve, reject) => {
var sql = "select id from users where id=?";
db.getResult(sql, [userId], (result) => {
if (result.length > 0) {
resolve(true);
} else {
resolve(false);
}
});
});
}
}
//// in you main or you controller file
// use the function
const { findUserById } = require('./model')
app.get('/user/:id', (req, res) => {
let sql = 'select * from "users" where "userId"= $1';
findUserById(sql, 1)
.then(result => {
res.status(200).send({
data: result
})
})
.catch(error => {
res.status(400).send(error)
})
})
I'm using a Node.js server to make requests to an Azure sql database.
As far as I understand the following function does not prevent sql injection:
Current code: (working but unsafe)
var executeQuery = async function(query, response) {
const pool = new sql.ConnectionPool(dbConfig)
pool.on('error', err => {
console.log('sql errors', err);
});
try {
await pool.connect();
let result = await pool.request().query(query);
response.send(result.recordset);
return {success: result}
} catch (err) {
return {err: err};
} finally {
console.log('request complete')
pool.close(); // closing connection after request is finished
}
};
app.get("/api/workOrders/byId/:workOrderId", function(req, res) {
console.log(req.params);
var query = "SELECT * FROM [WorkOrder] WHERE [idWorkOrder]=" + req.params.workOrderId;
executeQuery(query, res);
});
I would like to have the executeQuery function standalone, but I did not find an answer for that yet. Anyway, this is the code I constructed from mssql documentation:
New Code (not working)
app.get("/api/test/:workOrderId", function(req, res) {
console.log(req.params.workOrderId);
(async function() {
const pool = new sql.ConnectionPool(dbConfig)
pool.on('error', err => {
console.log('sql errors', err);
});
try {
await pool.connect();
let result = await pool.request()
.input('input_parameter', sql.VarChar(50), req.params.workOrderId)
.query('SELECT * FROM [Quotation] WHERE [idWorkOrder]= #input_parameter');
console.log(result);
res.send(result.recordset);
return {success: result}
} catch (err) {
return {err: err};
} finally {
console.log('request complete')
pool.close(); // closing connection after request is finished
}
});
})
This version should be injection proof, but It does not return anything. Is there an option to pass the input values to the executeQuery function as in the current code?
You can pass the value of req.params.workOrderId into your async function and then use that value inside. check the following code.
app.get("/api/test/:workOrderId", function(req, res) {
console.log(req.params.workOrderId);
(async function(workOrderId) {
const pool = new sql.ConnectionPool(dbConfig)
pool.on('error', err => {
console.log('sql errors', err);
});
try {
await pool.connect();
let result = await pool.request()
.input('input_parameter', sql.VarChar(50), workOrderId)
.query('SELECT * FROM [Quotation] WHERE [idWorkOrder]= #input_parameter');
console.log(result);
res.send(result.recordset);
return {success: result}
} catch (err) {
return {err: err};
} finally {
console.log('request complete')
pool.close(); // closing connection after request is finished
}
})(req.params.workOrderId); // <===pass value to the function
})
I have the following async method:
alreadyLoaded: async function (id) {
const pool = await poolPromise;
return pool.request()
.input('idParameter', id)
.query('SELECT count(*) AS value FROM dbo.partidos WHERE id=#idParameter')
.then(result => {
console.log(result.recordset[0].value)
result.recordset[0].value > 0
}).catch(function(err) {
console.log(err.message);
});
Invoked in another one:
processMatches: function(payload) {
payload.matches.forEach(p => {
if(partidosRepository.alreadyLoaded(p.id))
{
console.log("El partido ya fue cargado.");
return;
}
The alreadyLoaded method checks if some record is already inserted on database, and it's invoked inside another method to validate. The problem here is that the processMatches method continues processing records before the alreadyLoaded finishs with the current one.
I'm having a wrong manage of promises here, Can anyone help me solve this out?
Here's the database connection:
const poolPromise = new sql.ConnectionPool(config)
.connect()
.then(pool => {
console.log('Connected to localhost '+ config.database +' database');
return pool;
})
.catch(err => console.log('Database connection failed. Error: ', err));
module.exports = {
sql, poolPromise
}
Why don't you build your if statement like this
if(await partidosRepository.alreadyLoaded(p.id))
also keep in mind you are not returning boolean value here
}).catch(function(err) {
console.log(err.message);
});
When I load my page I want some products to be shown, so I make a GET request and it retrieves them from the database. However, when I refresh the page I notice the old connection remains. How to make sure the old connections close?
Here's my code:
const MongoClient = require('mongodb').MongoClient;
const connection = (closure) => {
return MongoClient.connect(config.connectionString, (err, client) => {
if (err) {
return winston.log('error', now() + err);
}
closure(client);
});
};
...
router.get('/products', (req, res) => {
connection((client) => {
client.db('dbname').collection('collectionname')
.find({})
.toArray()
.then((products) => {
response.data = products;
response.message = "Products retrieved successfully!"
res.json(response);
})
.catch((err) => {
winston.log('error', now() + err);
sendError(err, res);
});
});
});
Well, each time your /products route is called, you do create a new MongoClient instance. In that extent to limit the number of connection to your Database, you may either connect once, and save your MongoClient instance:
let client = undefined;
const connection = (closure) => {
// Return the client if any...
if(client) return closure(client);
return MongoClient.connect(config.connectionString, (err, c) => {
if (err) {
return winston.log('error', now() + err);
}
// Save the client.
client = c;
closure(client);
});
};
...or simply close the MongoClient connection you instantiated once you're done with it:
router.get('/products', (req, res) => {
connection((client) => {
client.db('dbname').collection('collectionname')
.find({})
.toArray()
.then((products) => {
response.data = products;
response.message = "Products retrieved successfully!"
// Close the MongoClient...
client.close();
res.json(response);
})
.catch((err) => {
winston.log('error', now() + err);
sendError(err, res);
// Close the MongoClient...
client.close();
});
});
});
I would advise you to go with the first solution: The MongoClient maintains a connection pool, so having multiple clients does not have any advantages. In addition, it allows you to check whether or not the DB is remotely available, before executing anything else as well (just connect to the DB on your app init(), and save the client instance, and you'll be done).
I have tried everything and can't figure out what i am doing wrong. I have no problem posting data from the client to the server but the other way around i can't get it to work.
The only response i get in my client is ReadableByteStream {}.
This is my code on the client:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
console.log(res.body)
return dispatch(getAllQuestionnairesSuccess(res.body));
} else {
throw new Error("Oops! Something went wrong");
}
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}
This is my code on the server:
exports.all = function(req, res) {
var allQuestionnaires = [];
Questionnaire.find({}).exec(function(err, questionnaires) {
if(!err) {
console.log(questionnaires)
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ a: 1 }));
//res.json(questionnaires)
}else {
console.log('Error in first query');
res.status(400).send(err);
}
});
}
I'm doing some guesswork here, since I'm not sure what flavor of fetch you are currently using, but I'll take a stab at it based on the standard implementation of fetch.
The response inside the resolution of fetch typically does not have a directly readable .body. See here for some straight forward examples.
Try this:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
return res.json();
} else {
throw new Error("Oops! Something went wrong");
}
})
.then(json => {
console.log(json); // response body here
return dispatch(getAllQuestionnairesSuccess(json));
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}