I'm trying to update the status for every ticket in the database by fetching all the tickets from database and then passing it to the API.
The API returns me a status which I want to update against every ticket in the database.
My code looks fine to me, but the table is not being updated.
I tried console.log() for both ticketNumber as well as info.status.name, they both are printing correct values as well.
NOTE: URL is a combination of urlcomeshere/ticketNumber
something like https://api-example.com/BCA-123
connection.query(`SELECT ticket_Number FROM tickets`, function(
err,
result,
fields
) {
var totalTickets = result.length;
for (var i = 0; i < totalTickets; i++) {
ticketNumber = result[i].ticket_Number;
var infix = "urlcomeshere/";
infix += ticketNumber;
var options = {
method: "GET",
url: infix,
auth: {
username: "username comes here",
password: "password comes here"
},
headers: {
Accept: "application/json"
}
};
request(options, function(error, response, body) {
info = JSON.parse(body)["fields"];
var updateTickets = `UPDATE tickets SET status = "${info.status.name}" WHERE ticket_Number = "${ticketNumber}"`;
connection.query(updateTickets, function(err, result) {
console.log("Updated ticket Status");
});
});
}
});
Since it is you are calling an async function your application won't know when will it end or execute, and the thread might be ended before your query is executed.
Below the example i tried to separate the query function and promisify it.
Read:
Promisification
const somefunction = () => {
connection.query(`SELECT ticket_Number FROM tickets`, function(
err,
result,
fields
) {
var totalTickets = result.length;
const promises = []
for (var i = 0; i < totalTickets; i++) {
ticketNumber = result[i].ticket_Number;
var infix = "urlcomeshere/";
infix += ticketNumber;
var options = {
method: "GET",
url: infix,
auth: {
username: "username comes here",
password: "password comes here"
},
headers: {
Accept: "application/json"
}
};
promises.push(updateTicketQuery(options, body, ticketNumber))
}
await Promise.all(promises)
});
}
const updateTicketQuery = (options, body, ticketNumber) => {
return new Promise((resolve, reject) => {
request(options, function(error, response, body) {
coonst info = JSON.parse(body)["fields"];
var updateTickets = `UPDATE tickets SET status = "${info.status.name}" WHERE ticket_Number = "${ticketNumber}"`;
connection.query(updateTickets, function(err, result) {
if(err) {
reject(err)
} else {
console.log("Updated ticket Status");
resolve(result)
}
});
});
})
}
Related
I am basically trying to say, if someone types into the browser, xxx.com/homy, instead of xxx.com/home, how do I redirect them to a 404 page? here's my index.js file. I am using node.js
// Direct to View Registrations
router.get('/viewRegistration', auth.ensureAuthenticated, function(req, res, next) {
var adminActive = ""
UtilRole.roleCheck(req, res, 'ADMIN', (response) => {
adminActive = response != undefined ? response : false
const user = JSON.parse(req.session.passport.user)
var query = "SELECT * FROM table WHERE email = '" + user.emailAddress + "'";
ibmdb.open(DBCredentials.getDBCredentials(), function(err, conn) {
if (err) return res.send('sorry, were unable to establish a connection to the database. Please try again later.');
conn.query(query, function(err, rows) {
if (err) {
Response.writeHead(404);
}
for (var i = 0; i < rows.length; i++) {
console.log(rows[i])
}
res.render('viewRegistration', {
page_title: "viewRegistration",
data: rows,
user,
role: adminActive
});
return conn.close(function() {
console.log('closed /viewRegistration');
});
});
});
})
})
module.exports = router;
I have a lambda function that connects to mysql and runs a set of queries, but I actually have a sequence of mysql queries that need to run one after another. I.e., the value of one query is used in the next query, etc.
Currently, I have a bunch of callbacks to achieve this, but this is leading to "callback hell". How would I rewrite this to use async / await?
My code is actually split into 2 files. The first file does an initial query, and then the value is passed into a function of the second file. Please note that the mysql node_module is included but not shown here. The AWS API gateway calls index.js
// index.js
var mysql = require('mysql'); // from node_modules
var config = require('./config.json');
var dashboard = require('./dashboard.js');
var pool = mysql.createPool({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
// check for mysql connection error first
if ( err ) {
throw err;
}
let qry = "select id from some_table where some_field = ?";
let someval = event.queryStringParameters.someval;
connection.query(qry, [someval], function(error, result) {
if ( error ) {
throw err;
}
else {
dashboard.processRequest(connection, callback, event, res[0].id);
}
});
});
}
// dashboard.js
module.exports = {
jsonResponse: function(results) {
return {
"statusCode": 200,
"body": JSON.stringify({ results }),
"isBase64Encoded": false,
"headers": {
"Access-Control-Allow-Origin": "*"
}
};
},
processRequest: function(connection, callback, event, val) {
let qry = "update first_table set some_field = ?";
connection.query(qry, [val], function(error, results) {
// return to client if error
if (error) {
callback(null, this.jsonResponse(error));
}
else {
// assume that this table must be update AFTER the previous statement
qry = "select id from second_table where some_field = ?";
connection.query(qry, [val], function(error1, results1) {
// return to client if error
if ( error1 ) {
callback(null, this.jsonResponse(error1));
}
qry = "update third_table set some_field = ? where id = ?";
connection.query(qry, [results1[0].id], function(error2, results2) {
// release connection when all queries are completed
connection.release();
if ( error2 ) {
callback(null, this.jsonResponse(error2));
}
else {
callback(null, this.jsonResponse(results2));
}
});
});
}
});
}
};
It was suggested to me that something like the below code might work. Unfortunately, it does not. I was curious to know why using try...catch blocks in the way shown below is not working, and is it the same thing as what you've shown, but just written differently?
// index.js
var mysql = require('mysql'); // from node_modules
var config = require('./config.json');
var dashboard = require('./dashboard.js');
var pool = mysql.createPool({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
// check for mysql connection error first
if ( err ) {
throw err;
}
let qry = "select id from users where username = ? limit 1;";
let username = event.queryStringParameters.username;
try {
let res = await connection.query(qry, [event.queryStringParameters.username]);
dashboard.processRequest(connection, callback, event, res[0].id);
} catch (err) {
console.log(err);
}
});
}
// dashboard.js
module.exports = {
jsonResponse: function (results) {
return {
"statusCode": 200,
"body": JSON.stringify({results}),
"isBase64Encoded": false,
"headers": {
"Access-Control-Allow-Origin": "*"
}
};
},
processRequest: async function (connection, callback, event, val) {
let qry = "update first_table set some_field = ?";
try {
let results = await connection.query(qry, [val]);
qry = "select id from second_table where some_field = ?";
try {
let results1 = await connection.query(qry, [val]);
qry = "update third_table set some_field = ? where id = ?";
try {
let results2 = await connection.query(qry, [results1[0].id]);
connection.release();
callback(null, this.jsonResponse(results2));
} catch (error2) {
callback(null, this.jsonResponse(error2));
}
} catch (error1) {
callback(null, this.jsonResponse(error1));
}
} catch (error) {
callback(null, this.jsonResponse(error));
}
}
};
We need use promises.
Typically I follow this approach:
Create one async method mainProcess and have bunch of methods step by step called with in that method. one after the other with await or all at once.
Each async method getConnection and runQuery in this case, called within mainProcess must a Promise.
If any errors from these methods i.e promise rejects from individual methods, goes in catch block of mainProcess().
If no errors, all methods within mainProcess gets executed and goes to then block of mainProcess()
Your code can be refactored like this (just wrote in an editor untested)
var pool = mysql.createPool({
host: config.dbhost,
user: config.dbuser,
password: config.dbpassword,
database: config.dbname,
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
/**
* Main Lambda Process
*/
const mainProcess = async () => {
// Get Connection
let connection = await getConnection();
// Run Step 1
let qry1 = "select id from some_table1 where some_field = ?";
const response1 = await runQuery(connection, qry1, { someFiledValue: 1222})
// Run Step 2
let qry2 = "select id from some_table2 where some_field = ?";
const resonse2 = await runQuery(connection, qry2, { someFiledValue: 1222})
return 'All Good';
});
}
mainProcess()
.then(result => {
// All lambda success messages are returned from here
callback(null, result);
})
.catch(error => {
// All lambda errors thrown from here
callback(error);
});
};
function getConnection(qry, parms) {
return new Promise((resolve, reject) => {
pool.getConnection(function (error, connection) {
if (error) {
// return to client if error
reject(error);
} else {
// Return response
resolve(connection);
}
});
});
}
/**
* Runs a query, either resolves or rejects
*/
function runQuery(connection, qry, parms) {
return new Promise((resolve, reject) => {
connection.query(qry, [val], function (error, results) {
if (error) {
// return to client if error
reject(error);
} else {
// Return response
resolve(result);
}
});
});
}
When you're dealing with a lambda function which performs an async task you have two solutions:
you can use non async handlers, in which case you need to invoke "callback" on promises as you did in your example
you can use async handlers, which does not requires the "callback" input and that allows you to write async/await code, like the following example:
const mysql = require('mysql2/promise');
exports.handler = async(event, context) => {
//get path variable
const { pathVar } = event.pathParameters;
// get connection
const connection = await mysql.createConnection({
host : process.env.RDS_HOSTNAME,
user : process.env.RDS_USERNAME,
password : process.env.RDS_PASSWORD,
database : process.env.RDS_DB_NAME
});
// get text query
const textQuery = `SELECT field FROM entity WHERE attribute = ${pathVar}`;
// get res
const results = await connection.execute(textQuery);
return {
"statusCode": 200,
"body": results,
"isBase64Encoded": false
}
}
You can have a look at the AWS docs: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html
pool.getConnection(function(err, connection) {
var yesterday = new Date(Date.now() - 864e5);
var dd = yesterday.getDate();
var mm = yesterday.getMonth() + 1; //January is 0!
var yyyy = yesterday.getFullYear();
// Use the connection
connection.query("SELECT id, restaurant_id, revenue_id, revenue_name, total_cash,visa,mc,amex,
DATE_FORMAT(business_date, '%d-%M-%Y') as business_date, item_sales FROM `alfred-
prod`.report_day_sales where restaurant_id=19 and DATE_FORMAT(business_date, '%Y-%m-%d') =
DATE_FORMAT('2014-09-01', '%Y-%m-%d')", function (error, results, fields) {
console.log("SELECT id, restaurant_id, revenue_id, revenue_name, total_cash,visa,mc,amex,
DATE_FORMAT(business_date, '%d-%M-%Y') as business_date, item_sales FROM `alfred-
prod`.report_day_sales where restaurant_id=230 and DATE_FORMAT(business_date, '%Y-%m-%d') =
DATE_FORMAT('"+yyyy+"-"+mm+"-"+dd+"', '%Y-%m-%d')")})
});
const response = {
statusCode: 200,
body: JSON.stringify(
https.get('https://postman-echo.com/get?'+
'username ='+
'&password ='+
'&date=' + results[0].business_date +
'&cashSales='+ results[0].total_cash +
'&creditCardVisa='+ results[0].visa +
'&creditCardMaster='+ results[0].mc +
'&creditCardAmex=' + results[0].amex +
'&creditCardOthers=0',
res => {
//console.log(res.statusCode);
//console.log(res.headers);
let body = '';
res.on('data',data =>{
body += data;
})
res.on('end',()=>console.log(body));
})
),
};
return response;
};
I'm trying to get a response from the http request, with results[0].business date, results[0].total_cash and everything else. But I get an error instead of an output. This is the error -
Response:
{
"errorType": "ReferenceError",
"errorMessage": "results is not defined",
"trace": [
"ReferenceError: results is not defined",
" at Runtime.exports.handler (/var/task/index.js:45:27)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
I think this is what you are trying to do. If i am understanding you correctly, You are trying to query mysql to get the results and using that result to send an http request.
const https = require("https");
const getResults = () => {
const queryResponse = await new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
var yesterday = new Date(Date.now() - 864e5);
var dd = yesterday.getDate();
var mm = yesterday.getMonth() + 1; //January is 0!
var yyyy = yesterday.getFullYear();
const query = "SELECT id, restaurant_id, revenue_id, revenue_name, total_cash,visa,mc,amex, DATE_FORMAT(business_date, '%d-%M-%Y') as business_date, item_sales FROM `alfred-\
prod`.report_day_sales where restaurant_id = 19 and DATE_FORMAT(business_date, '%Y-%m-%d') = DATE_FORMAT('2014-09-01', '%Y-%m-%d')"
// Use the connection
connection.query(query, (error, results, fields) => {
if (error) {
reject(error);
}
resolve(results)
})
});
});
return queryResponse;
}
exports.handler = async (event) => {
const httpResponse = await new Promise((resolve, reject) => {
const results = await getResults();
const { business_date, total_cash, visa, mc, amex } = results[0]
https.get(
`https://postman-echo.com/get?username=&password=&date=${business_date}&cashSales=${total_cash}&creditCardVisa=${visa}&creditCardMaster=${mc}&creditCardAmex=${amex}&creditCardOthers=0`,
resp => {
let body = '';
// A chunk of data has been recieved.
resp.on("data", chunk => {
body += chunk;
});
// The whole response has been received. Print out the result.
resp.on("end", () => {
resolve(body);
});
resp.on("error", error => {
reject(error);
});
}
);
});
const response = {
statusCode: 200,
body: JSON.stringify(httpResponse),
};
return response;
};
Note: I haven't tested this code, Also this is not a complete code.
I have a code in Node 6.10 and it is working...
But If I convert it to Node 8.10 it's not working
var mysql = require("mysql");
var connection = mysql.createConnection({
host: " localhost",
user: "root",
password: "",
database: "parser_db"
});
exports.handler = async event => {
connection.connect();
let response = {
statusCode: 400,
body: { Method: "Invalid", event }
};
var readTable = "SELECT * FROM documents where id = " + mysql.escape(1);
connection.query(readTable, function(err, results, fields) {
if (err) throw err;
else {
response = {
statusCode: 200,
body: { results }
//body: { results }
};
console.log(response);
return response;
}
});
};
Can some one please help me to detect the problem. It is also not working if I do the MySQL query in separate file and return the result set.
Note : If I print the result using console.log(response) instead returning it's
showing the correct result.
The problem is that you are returning response from within the connection.query() callback function. That makes response the return value for the callback function, not the return value for the outer Lambda function.
One way to restructure this code is as follows:
exports.handler = async (event) => {
connection.connect();
return new Promise((resolve, reject) => {
const readTable = `SELECT * FROM documents where id = ${mysql.escape(1)}`;
connection.query(readTable, (err, results, fields) => {
if (err) {
reject(err);
} else {
resolve({statusCode: 200, body: {results}});
}
});
});
};
In addition to #jarmod's answer, You can also use the util.promisify method to promisify connection.query so that you can use the await keyword, to make the code simpler
const util = require('util');
exports.handler = async (event) => {
connection.connect();
const readTable = `SELECT * FROM documents where id = ${mysql.escape(1)}`;
const connQueryPromisified = util.promisify(connection.query).bind(connection);
const result = await connQueryPromisified(readTable);
return {statusCode: 200, body: {results}};
};
I am not sure how to fetch particular data in column from JSON with the help of keys. From ajax request i am getting data from the server but i want to store it in sqlite as the columns in server
$("#xxx").click(function()
{
var e = $("#mob").val();
var p = $("#key").val();
myDB.transaction(function(transaction)
{
transaction.executeSql('CREATE TABLE IF NOT EXISTS User_data (data)', [],
function(tx, result)
{
navigator.notification.alert("table created");
},
function(error)
{
navigator.notification.alert("error, table exists");
});
});
$.ajax
({
url: "http://192.168.1.4/sms/android.php",
type: "GET",
datatype: "json",
data: { type:'login', phone: e, name: p },
ContentType: "application/json",
success: function(response)
{
var valuesInArray = JSON.stringify(response);
var user_data = JSON.parse(valuesInArray);
for(var item in user_data.Users)
{
myDB.transaction(function(transaction)
{
transaction.executeSql('INSERT INTO User_data (id,date_closed) VALUES (item.id,item.date_closed)', [],
function(tx, result)
{
navigator.notification.alert("data inserted");
},
function(error)
{
navigator.notification.alert("error, table exists");
});
});
}
},
error: function(e)
{
alert('Got ERROR: ' + JSON.stringify(e));
}
});
});
here is the image of the data i am getting from the server
DATA IN ALERT BOX
here, i want to fetch each column in the database.
Thankx in advance.
<?php
header('Access-Control-Allow-Origin:*');
pg_connect("host=localhost port=5432 dbname=** user=** password=***");
if(isset($_GET['type']))
{
if($_GET['type'] == "login")
{
$mobile = $_GET['phone'];
$key = $_GET['name'];
$query = "select * from crm_lead where phone='$mobile' and id='$key'";
$result = pg_query($query);
while($myrow = pg_fetch_assoc($result))
{
$recipes[]=$myrow;
}
$output = json_encode(array('Users' => $recipes));
echo "'".$output."';";
}
}
else
{
echo "invalid";
}
pg_close();
?>
Why can't you use the response object directly since it's already a Json object?
var users = response.Users;
for(var i=0; i < users.length;i++)
{
var id = users[i].id;
//do something with id
}
$.ajax
({
url: "http://182.70.240.81:82/sms/android.php",
type: "GET",
datatype: "json",
data: { type: 'login', phone: 9770869868, name: 14 },
ContentType: "application/json",
success: function (response) {
var simpleJson = JSON.parse(response);
var shortName = 'db_test';
var version = '1.0';
var displayName = 'Test Information';
var maxSize = 65536; // in bytes
var db = openDatabase(shortName, version, displayName, maxSize);
db.transaction(function (txe) {
txe.executeSql('DROP TABLE User_data');
txe.executeSql('CREATE TABLE User_data(id INTEGER,date_closed TEXT)');
db.transaction(function (txe1) {
for (var i = 0; i < simpleJson.Users.length; i++) {
txe1.executeSql('INSERT INTO User_data (id,date_closed) VALUES (' + simpleJson.Users[i].id + ',"' + simpleJson.Users[i].date_closed + '")', [],
function (tx, result) {
alert("data inserted");
},
function (error) {
alert("error, table exists");
});
}
});
});
}
});
Remove Single Qoutaion from your json: