Node.js PostgreSQL http - Uncaught error on UPDATE query - javascript

This is my server.js. I am creating a simple CRUD todo app.
I am making requests from another NodeJS script.
When I make a PUT request I found (by using breakpoints) that I get an uncaught error: source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression. Even though it is just a simple UPDATE query.
Any help is appreciated.
if (method == "PUT" && /\/todos\/(\S+)\/$/.test(url)) {
console.log("PUT request at", url);
const urlId = url.match(/\/todos\/(\S+)\/$/);
console.log(urlId);
try {
let jsonData = "";
req.on("data", chunk => {
jsonData += chunk;
});
req.on("end", async () => {
const data = JSON.parse(jsonData);
console.log([String(data["description"]), Number(urlId[1])]);
const updateTodo = await pool.query(
"UPDATE todo SET description = '$1' WHERE todo_id = $2 RETURNING *;",
[String(data["description"]), Number(urlId[1])]
); // ERROR
console.log(JSON.stringify(updateTodo));
res.setHeader("Content-Type", "application/json");
res.write(JSON.stringify(updateTodo["rows"]));
res.end();
});
} catch (err) {
console.error(err);
res.end();
}
}
Database -
CREATE DATABASE learn_restapi
CREATE TABLE todo(
todo_id SERIAL PRIMARY KEY,
description VARCHAR(255)
);
One thing I found is a bug report.

Finally, found the bug.
Rather than specifying the types in the description and todo_id in the UPDATE query, just passing them as strings work.
Also get rid of the single quotes from the query.
This is the updated async function:
req.on("end", async () => {
const data = JSON.parse(jsonData);
console.log([data["description"], urlId[1]]);
const updateTodo = await pool.query(
"UPDATE todo SET description = $1 WHERE todo_id = $2;",
[data["description"], urlId[1]]
);
res.setHeader("Content-Type", "application/json");
res.write(JSON.stringify("Todo was updated!"));
res.end();
});
I also got rid of the RETURNING statement from the query.
This seem to resolve the issue for me.

Related

I'm unable to send a response to my react.js using http.get in node

I'm trying to get the temperature data from my node.js backend sent to react.js but i kept getting res.send is not a funtion
Sample code here
app.get("/gettemperature", (req, res) => {
const email = req.query.email;
let stmt = `SELECT * FROM users WHERE email=?`;
let todo = [email];
db.query(stmt, todo, (err, results, fields) => {
if (err) {
console.error(err.message);
}
if(results.length > 0 ){
let id = results[0].id;
let getID = `SELECT * FROM controlModules WHERE deviceowner=?`;
let getidData = [id];
db.query(getID, getidData, (err, resulta, fields) => {
if (err) {
console.error(err.message);
}
if(resulta.length > 0){
let lanip = resulta[0].ipaddress;
let url = "http://"+lanip+"/data";
http.get(url,(res) => {
let body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
try {
let json = JSON.parse(body);
const temp_actual = json.temperature.value;
console.log(temp_actual);
res.setHeader('Content-Type', 'application/json');
res.end(
JSON.stringify({
value: temp_actual
})
);
} catch (error) {
console.error(error.message);
};
});
}).on("error", (error) => {
console.error(error.message);
});
}
});
}
});
});
i really need to return/send/respond the temperature data to my front end but i'm getting said error, is there a different way to return data?
It looks like you are mixing up an HTTP server you wrote in Node (although you haven't shown any relevant code) and an HTTP client you also wrote in Node.
res is an argument received by the callback you pass to http.get and contains data about the response received by your HTTP client.
Meanwhile, somewhere else (not shown) you have a different variable also called res which is the object your HTTP server uses to send its response to the browser running your React code.
You are calling res.send and wanting res to be the latter but it is really the former.
Since you haven't shown us the HTTP server code, it is hard to say where that res is, but there is a good chance you have shadowed it and can solve your problem by using different names (e.g. client_res and server_res).
That said. I strongly recommend avoiding using the http module directly as the API follows out of date design patterns and isn't very friendly. Consider using fetch or axios for making HTTP requests and Express.js for writing HTTP servers.

Unknown column in where clause in NextJS API

I'm writing an API which would fetch data from a MySQL table based on a category. The code currently looks like this.
import { sql_query } from "../../../lib/db"
export default async function handler(req, res) {
var category = 'Starters'
if (req.method === 'GET') {
try {
const results = await sql_query({
query_string: `SELECT * FROM products WHERE category = ${category}`
})
return res.status(200).json(results)
} catch (error) {
res.status(500).json({ message: error.message })
}
}
}
This isn't going through for some reason and instead, I see this error message
{"message":"ER_BAD_FIELD_ERROR: Unknown column 'Starters' in 'where
clause'"}
From what I know, my MySQL query is fine because it works okay in PHPMyAdmin. Can anyone point out what I'm doing wrong here?
The error indicates the parameter is being injected and used in the context of a column name, you need to contain it within quotes:
`SELECT * FROM products WHERE category = '${category}'`

PG-Promise Proc Erroring Out with Unknown Parameter Type

We are attempting to write a PostgreSQL Procedure to insert data into a table. We have created the procedure and ran said procedure with the variables below and it inserts just fine. However, when we try to use pg-promise with our express server, our string parameters are being read as unknown. When we iterate over the post body, we see that each parameter is reading as the type we expect to go in, and PostgreSQL is reading integer correctly, but it isn't reading string correctly. I've attempted to use the as.text function and it sends in the parameter value as "''" but that still reads as unknown. Is there something we are missing to successfully post the data?
let createInspection = async (req, res, next) => {
try {
let params = [];
for (let prop in req.body) {
console.log(typeof req.body[prop]);
params.push(req.body[prop]);
}
console.log(params)
let data = await db.proc('Inspections_Create', params);
res.status(200)
.json({
status: 'success',
data: data,
message: 'Inserted Inspection'
});
}
catch (error) {
return next(error);
}
}

Long running Node REST API takes much time to respond

I have a Rest API in node.js that takes much time to respond because it sends a request to suppliers vendor and once the response is fully prepared then it returns the result what I want is as the result is being prepared it should be able to display it on the front react side. Thanks in advance for any help and your time
here is my controller
module.exports.search = async (req, res) => {
try {
let params = req.query;
params = _.extend(params, req.body);
const result = await modules.Hotel.Search.search(req.supplierAuth, params);
res.json(result);
} catch (e) {
global.cli.log('controller:hotels:search: ', e);
res.status(500).json({ message: e.message });
}
};
here is my front side service
export const getHotels = (filters, options = {}) => {
const queryString = new URLSearchParams(options).toString();
return post(`/api/hotels/search?${queryString}`, filters);
};
The best solution is to use streams and pipe() the results as they come into express's res object, similar to this guy's approach.
You'll have to modify the modules.Hotel.Search.search(....) and make that use streams.

Empty object returned from gRPC Server

Basically, the JSON object that's returned from a callback in my gRPC server is empty no matter what I do.
For the most part I'm following this tutorial, except I'm using a SQLite3 server instead of knex, and I've worked to the listProducts method. I haven't tried working on the other product methods yet.
In server.js I get some data from a SQLite3 database, and try to return it in a callback (at the bottom of the method). I also print out the data from the DB to confirm I'm actually getting valid data.
gRPC server.js
function listProducts(call, callback) {
console.log("******** Listed the products *********");
var data = "";
let db = new sqlite3.Database('../data/testDB.db', sqlite3.OPEN_READONLY, (err) => {
if(err){
console.error(err.message);
}
console.log("connected to DB");
});
db.serialize(() => {
db.get('SELECT NAME as name FROM PEEPS', (err, row) => {
if(err){
console.error(err.message);
}
console.log(row.name);
data.name = row.name;
});
});
db.close((err) => {
if(err) {
console.error(err.message);
}
console.log('closed db');
});
callback(null, { products: data.name });
}
Out put from gRPC server.js
******** Listed the products *********
connected to DB
Jeff // Correct data from DB.
closed db
The callback returns to client.js, where it was called. However, the object is always empty.
If I uncomment res.json({ name: "jessie" }); and comment res.json(result);, the code works as expected; name: jessie is sent to the browser as a JSON object.
So that tells me that from the client to the browser the data is being handled correctly. Therefore the problem is when the data is passed from the server.js to client.js.
gRPC client.js
// requirements
const path = require('path');
const protoLoader = require('#grpc/proto-loader');
const grpc = require('grpc');
// gRPC client
const productProtoPath = path.join(__dirname, '..', '..', 'protos', 'product.proto');
const productProtoDefinition = protoLoader.loadSync(productProtoPath);
const productPackageDefinition = grpc.loadPackageDefinition(productProtoDefinition).product;
const client = new productPackageDefinition.ProductService('localhost:50051', grpc.credentials.createInsecure());
// handlers
const listProducts = (req, res) => {
client.listProducts({}, (err, result) => {
console.log(result);
console.log(typeof result);
// console.log(res.json(result));
res.json(result);
// res.json({ name: "jessie" });
console.log("*******************");
});
};
Output from gRPC client.js
Server listing on port 3000
{} //Oh no! An empty JSON object!
object
*******************
Edit
Here is a link to my repository: https://github.com/burke212/grpc-node
The main problem here is that in your server code, your db methods are asynchronous but you are trying to access the result synchronously. You need to call the main callback for listProducts in the callback for db.get to ensure that you have the result of that database request before trying to use it. After making this change your listProducts method implementation should look more like this:
function listProducts(call, callback) {
let db = new sqlite3.Database('../data/testDB.db', sqlite3.OPEN_READONLY);
db.serialize(() => {
db.get('SELECT NAME as name FROM PEEPS', (err, row) => {
if(err){
console.error(err.message);
}
// Call the callback here to use the result of db.get
callback(null, { products: row.name });
});
});
db.close();
}
For simplicity I omitted the logging. Also, the sqlite3.Database constructor and db.close do not have callbacks in the example in the sqlite3 README. I suggest checking again whether those functions actually take callbacks.
In addition to that, now that you have shared the product.proto file that defines your service, there is another problem. The listProducts method in the ProductService service is declared as returning a ProductList object. In that message type, the products field must be an array of Product objects. All of the code in your method implementation is directed towards returning a string in that field, and that does not result in a compatible object.

Categories

Resources