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}'`
Related
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.
I am very new to JS and I'm trying to create an API using node.js however I'm getting the error:
Uncaught error: invalid input syntax for type integer: "NaN"
The requests are fine when I do a GET and POST request but I'm having trouble with the PUT and DELETE. I get the same error with both requests. Here is my code:
const getProfiles = (request, response) => {
pool.query('SELECT * FROM profiles', (error, results) => {
if (error) {
throw error
}
response.status(200).json(results.rows)
})
}
const addProfiles = (request, response) => {
const {name, bio} = request.body
pool.query(
'INSERT INTO profiles (name, bio) VALUES ($1, $2) RETURNING id',
[name, bio],
(error) => {
if (error) {
throw error
}
response.status(201).json({status: 'success', message: 'Profile added.'})
})
}
const updateProfiles = (request, response) => {
const id = parseInt(request.params.id)
const {name, bio} = request.body
pool.query(
'UPDATE profiles SET name = $1, bio = $2 WHERE id = $3 RETURNING id',
[name, bio, id],
(error) => {
if (error) {
throw error
}
response.status(202).json({status: 'success', message: 'Profile updated with ID: ${id}'})
})
}
const deleteProfiles = (request, response) => {
const id = parseInt(request.params.id)
pool.query(
'DELETE FROM profiles WHERE id = $1', [id],
(error, results) => {
if (error) {
throw error
}
response.status(203).send(`Profile deleted with ID: ${id}`)
})
}
app
.route('/profiles')
// GET endpoint
.get(getProfiles)
// POST endpoint
.post(addProfiles)
//UPDATE endpoint
.put(updateProfiles)
// DELETE endpoint
.delete(deleteProfiles)
// Start server
app.listen(process.env.PORT || 3002, () => {
console.log(`Server listening`)
})
I am very much new to this and if you spot where I went wrong I would very much appreciate and explanation for me to better understand it and never make this mistake again. Thank you.
As far as I can see, req.params.id is undefined, because you are not telling express that route should receive a param.
Change this:
app
.route('/profiles')
// GET endpoint
.get(getProfiles)
// POST endpoint
.post(addProfiles)
//UPDATE endpoint
.put(updateProfiles)
// DELETE endpoint
.delete(deleteProfiles)
To this:
app
.route('/profiles')
// GET endpoint
.get(getProfiles)
// POST endpoint
.post(addProfiles)
app
.route('/profiles/:id') // :id means we are expecting that param
//UPDATE endpoint
.put(updateProfiles)
// DELETE endpoint
.delete(deleteProfiles)
And when you do the PUT or DELETE request, the endpoint should look like this: /profiles/
The error means you'r providing a "Not a Number" (NaN) where your app expects a number (integer).
It's most probably the id in the updateProfiles or deleteProfiles, because you haven't defined it your route
app
.route('/profiles/:id')
// GET endpoint
.get(getProfiles)
// POST endpoint
.post(addProfiles)
//UPDATE endpoint
.put(updateProfiles)
// DELETE endpoint
.delete(deleteProfiles)
While trying to fetch data from my express backend and MySQL database, with my react frontend using axios, it fails to set the fetched data using useState
my frontend function looks like this
const searchUser = () => {
Axios.post("http://localhost:3001/searchUser", {
username: username,
}).then((response) => {
if (response.data) {
setResult(response.data);
}
});
};
and my backend function looks like this
const searchUser = (req, res) => {
const keyword = req.body.username;
db.query(
"SELECT id,username FROM users WHERE username like ?",
"%" + keyword + "%",
(err, result) => {
if (err) {
res.json({ message: err });
console.log(err);
} else {
console.log(result);
res.json({ result });
}
}
);
};
I tried many methods while saving the data with the useState hook, I appreciate any help
While using Promises and then instead of async / await make sure to catch the errors if your fetch fails.
Unless you share with us the whole component that contains the searchUser function and how you defined the state i cannot pin point you on the error.
What i suggest you to do is adding a catch to your fetch by doing the following:
const searchUser = () => {
Axios.post("http://localhost:3001/searchUser", {
username: username,
}).then((response) => {
if (response.data) {
setResult(response.data);
}
}).catch((error) => {
console.error(error);
});
};
If any abnormalities has happened in your request the catch will tell you! Don't underestimate it's power.
Another path you can look into is console logging your output in front end searchUser function just before setting it in the state.
I did solve the problem, just by replacing res.json({ result }); to res.json(result); in the last line in my backend function
I'm trying to save multiple documents in mongodb using mongoose; and I'm also willing to prevent duplicates. my function looks sth like this:
const Stock = require('./models/stock')
let _symbol = 'symb'
const writeToDB = async (dataObj) => {
try {
let stock = await Stock.find({symbol : _symbol } , function (err) {
if(err) return null
})
if (!stock) {
stock = new Stock({
dataObj
})
await stock.save()
console.log(`${symbol} is successfully saved to database`)
} else {
stock = await Stock.updateMany(
dataObj, function (err) {
if (err) {
console.log(err)
} else {
console.log(`${symbol} successfully added`)
}
})
}
} catch (error) {
console.log(error)
}
}
but I keep getting timeout error. can someone pls inform me what's wrong.
update
with a well handled connection approach findOneAndUpdate()works fine
Using the upsert option, in findOneAndUpdate(). An upsert behaves like a normal findOneAndUpdate() if it finds a document that matches filter. But, if no document matches filter, MongoDB will insert one by combining filter and update as shown below
var query = {symbol : _symbol };
try{
let result = await Stock.findOneAndUpdate(query, dataObj, {upsert: true})
}
catch(err){
console.log();
}
if you have a big collection, for increase speed findOneAndUpdate(), you should indexed symbol field.
when you use async await, it's better don't use callback and use try catch
I think the best, simply and easy way to prevent duplicate values is use unique value in the schema.
So your Stock schema has to have something similar to this:
symbol:{
type: String, // or whatever
unique: true
}
If you try to insert two object with same value, mongoose will trhow an error like:
MongoError: E11000 duplicate key error dup key: { : "repeatedSymbol" }
Also you can check the documentation.
I want to get updated table values after I add user to my "WOD" table. For instance, I have 2 users in my WOD table and after I add third user , I want to return a response to client with I have just inserted data (third guy). But now , I can only return first 2 users because I can not take updated values. Of course I can make another query to get updated table values after I insert, but is there any better solution ? Here is my codes;
const addUser = async (req, res) => {
try {
const { userId, wodId } = req.body;
if (!userId || !wodId) {
res.status(400).send({ status: false, message: 'need userId and wodId' });
}
const wod = await Wod.findByPk(wodId, {
include: [
{
model: User,
as: 'Participants',
through: { attributes: [] }
}
]
});
//check capacity if full.
if (wod.Participants.length >= wod.capacity) {
res
.status(403)
.send({ status: false, message: 'Capacity of this class is full!' });
}
const result = await wod.addParticipants(userId);
res.status(201).json({ status: !!result, wod });
} catch (error) {
res.status(500).send({ status: result, message: error.message });
console.log(error.message);
}
};
As a result of many-to-many association sequelize.sync will generate some functions for us. You are used addParticipants function and this returns an array that added to the assocation(userwod) table.
In this array you will find some id fields(join table fields) because you just run like this INSERT INTO 'user_wods' ('user_id''wod_id') VALUES (2,1). If you want to return the added user's information then you should run a SELECT * FROM 'user' WHERE 'id'=2.
You must call reload function for fetch the third guy.
await wod.reload()