MySQL placeholders throw error on WHERE clause - mysql

I am using MySQL placeholders and create promise to use them with async await.
selectTickets: (variable) => {
const sqlStatement = `SELECT * FROM tickets WHERE userID = ?`;
return new Promise((resolve, reject) => {
db.query(sqlStatement, variable, (error, response) => {
if (error) return reject(error);
return resolve(response);
});
});
},
i tried even to create the statement with interpolation and gave me an error:
"Unknown column 'undefined' in 'where clause'"
This is my code. But when I am using it in react, I am getting Error 500 status saying that the statement is incorrect.
ode: 'ER_PARSE_ERROR',
errno: 1064,
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?' at line 1",
sqlState: '42000',
index: 0,
sql: 'SELECT * FROM tickets WHERE userID = ?'
I tried alot of other methods. But other functions that uses same type of function with same type of statement are working just fine.
In react I have this call:
const URL_TICKETS_BY_USERID = 'http://localhost:3000/api/get-tickets';
const config = {
headers: { Authorization: `Bearer ${user.token}` }
};
const userID = user.userID;
axios.get(URL_TICKETS_BY_USERID,
userID,
config
)
.then(data => console.log(data))
.catch(error => console.log(error))
Can i have some help?

The problem lies with your db.query() call. The second parameter should be an array, even for single values. This should work:
db.query(sqlStatement, [variable], (error, response) => {
if (error) return reject(error);
return resolve(response);
});
Also axios get() takes two parameters: url and config (optional). This means that any params should be part of that config object:
const config = {
headers: { Authorization: `Bearer ${user.token}` },
params: {
id: user.userID
}
};
axios.get(URL_TICKETS_BY_USERID, config)
Alternatively pass it as a GET parameter in the URL:
axios.get(URL_TICKETS_BY_USERID + "?id=" + user.userID, config)

In my case it was the question mark. In some database systems, the question mark is used as a placeholder for values that are passed in separately. However, it seems that in my case, the database system is not recognizing the question mark as a placeholder, and is interpreting it as part of the query.
So changed the query to:-
const q = `SELECT * FROM list WHERE userid = ${listId}`;
I passed the variable inside the query and it works now

Related

Strongly typing results from mysql2 in Typescript

I am working on an application using NextJS and Typescript and am attempting to determine the best way to properly type my MySQL responses. Here is the API endpoint:
import { hash } from "bcrypt";
import type { NextApiRequest, NextApiResponse } from "next";
import randomstring from "randomstring";
import { executeQuery } from "../../../lib/db";
const Test = async (req: NextApiRequest, res: NextApiResponse) => {
// Manage password generation
const password = randomstring.generate(16);
const hashedPassword = hash(password, 10);
// Create new auth using email and password
const auth = await executeQuery(
"INSERT INTO auth (email, password) VALUES (?, ?)",
["test#test.com", (await hashedPassword).toString()]
);
res.statusCode = 200;
res.json(auth.insertId);
};
export default Test;
I am wanting to strongly type insertId to remove all warnings and errors through ESLint, but unfortunately, every effort I have made has been unsuccessful. The error I am getting is:
Property 'insertId' does not exist on type 'RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[] | ResultSetHeader | { error: unknown; }'.
Property 'insertId' does not exist on type 'RowDataPacket[]'.ts(2339)
My executeQuery function is defined as:
import mysql from "mysql2/promise";
export const executeQuery = async (query: string, params: unknown[] = []) => {
try {
const db = await mysql.createConnection({
host: process.env.MYSQL_HOST,
database: process.env.MYSQL_DATABASE,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
});
const [results] = await db.execute(query, params);
db.end();
return results;
} catch (error) {
return { error };
}
};
One of my implementation attempts was this SO response but I could not get it to work...
Any and all help is greatly appreciated!
So, I managed to solve my own problem after tackling it for a while.
It turns out, I was doing my checks incorrectly.
Before calling auth.insertId, you'll want to include the following check:
if (!auth || !("insertId" in auth)) {
// Do something
}
That way, you don't actually have to type anything, because it can get super complicated when you are attempting to do that with mysql.
I did as well get myself in the same problem as you, after looking up in the mysql2 types files, I found you can pass the result type of the query.
For example:
connection.query<OkPacket>('INSERT INTO posts SET ?', {title: 'test'},
function (error, results, fields) {
if (error) throw error;
console.log(results.insertId);
});
For inserts and updates you can be using the OkPacket type and for selects you can use RowDataPacket. You can type it even further by implementing RowDataPacket to the expected responsey type of the query and passing it in the query function.
For example:
export interface Post {
title: string;
}
export interface PostRow extends RowDataPacket, Post {}
Then when you are querying you can pass as follows:
connection.query<PostRow[]>('SELECT * FROM posts WHERE id = 1',
function (error, results, fields) {
if (error) throw error;
// ...
});
Here it is my 2 cents, hope it helps someone in the future.

SQL Update statement no longer working after changing names

I changed some of the names in my update query and now it no longer works ;(. I get this error.
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE id = 42' at line 1",
sqlState: '42000',
index: 0,
sql: "UPDATE developers SET name = 'eyo', absent = '1', WHERE id = 42"
I changed slack_id into Name, changed everything like normal, but still doesn't work.
// UPDATE
app.put("/update", (req, res) => {
const id = req.body.id;
const name = req.body.name;
const absent = req.body.absent;
db.query("UPDATE developers SET name = ?, absent = ? WHERE id = ?" ,[name, absent, id],
(err, result) => {
if (err) {
console.log(err);
} else {
res.send(result);
console.log(result)
}
}
);
});
This Update redirects to my Axios.put
const updateDeveloper = () => {
try {
setSuccessMessageUpdate('');
setErrorMessageUpdate('');
Axios.put(`${url}/update`, { name: name, absent: absent, id: props.id }).then(
(response) => {
return (
{
id: props.id,
name: props.name,
slack_id: props.slack_id,
absent: props.absent,
selected: props.selected,
}
)
}
);
setSuccessMessageUpdate(`successfully updated developer `);
} catch (err) {
setErrorMessageUpdate('something went wrong');
}
};
I would say the rest of the code is irrelevant because the error is clearly mentioning a database issue. Maybe its a type error? I can't see it.
Never-mind I found the issue already. Seems the code is fine but after I saved I forgot to restart node, my bad.

INSERT into sql error - internal server error

I am trying to insert some data on my app. On my db.js:
usersDB.create = async (name, age, contact) => {
return new Promise((resolve, reject) => {
pool.query(
"INSERT INTO users(name=?, age=?, contact=?) VALUES(?,?,?)",
[name, age, contact],
(err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
}
);
});
};
Then on my router.js:
router.post("/", async (req, res) => {
try {
let results = await db.create(
req.body.name,
req.body.age,
req.body.contact
);
res.send({ message: "Created users" });
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
This however, returns an INTERNAL SERVER ERROR on postman and returns the ff on my console:
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '='Your Builder', age=25, contact=689566) VALUES(?,?,?)' at line 1"
Any idea what am I missing here? How do I fix it?
This line:
"INSERT INTO users(name=?, age=?, contact=?) VALUES(?,?,?)"
Contains a SQL Syntax error. Change it like this:
"INSERT INTO users (name, age, contact) VALUES (?,?,?)"
You first list the fields, without assigning anything to the single field, then you list the values you want to insert.

User entries not updating in database

I am using postman to send a request and I see Success message but in the database, it's not updated at all.
PostMAN request
database Snap shot
update services object: from this file I have used a database query to insert data in the database and set callBack funtion
const pool = require('../../config/database')
module.exports = {
updateUser: (data, callBack) => {
pool.query(
`UPDATE users SET firstName=?,email=?,password=?,lastName=?,phoneNumber=?, sex=? WHERE id=?`, [
data.firstName,
data.email,
data.password,
data.lastName,
data.phoneNumber,
data.sex,
data.id
], (error, results, fields) => {
if (error) {
return callBack(error)
}
return callBack(null, results)
}
)
}
}
update user controller here I have added a controller to update the user details which receive the data from update user services.
const {
create,
getUserbyID,
getUsers,
updateUser,
deleteUser,
getUserByEmail
} = require('./userService')
const {genSaltSync, hashSync, compareSync} = require('bcrypt')
const { sign } = require('jsonwebtoken')
module.exports ={
updateUser: (req, res) => {
const body = req.body;
const salt = genSaltSync(10);
body.password = hashSync(body.password, salt);
updateUser(body, (err, results) => {
if (err) {
console.log(err)
return false;
} // added
console.log("this is the body: "+JSON.stringify(req.body))
console.log("this is the results: "+ JSON.stringify(results))
if (!results) {
return res.json({
success:0,
message: "failed to update user"
})
}
return res.json({
success: 1,
message: "Updated Sucessfully"
})
})
},
}
router.js
router.patch('/update',checkToken, updateUser)
ADDED console.log
this is the body: {"Id":15,"firstName":"joey","email":"joey.chandler357#gmail.com","password":"$2b$10$ZBnRppSKAfQ1TrzGvs/wqOrVx/shb6ESJ7emXnC7IlWRN3VUGgfK2","lastName":"chandler","phoneNumber":"9860316634","sex":"Male"}
this is the results: {"fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
I can see your console.log message
this is the results: {"fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
Here you can notice affectedRows: 0 it means no row updated this happens when condition is not matched with any of the records. In postman you are passing "Id" I is in capital format but at the time of accessing this in service you are using "data.id" id is small latter so this is creating problem
we can handle this
instead of
if (!results) {
return res.json({
success:0,
message: "failed to update user"
})
}
use
if (!results.affectedRows) {
return res.json({
success:0,
message: "failed to update user"
})
}
this will be much better then previous check
I think you need to use an "insert" to add the db record. It's using an update... so it's looking for a pre-existing record.
Try two things:
wrap “users” in quotes on your update query. I’ve seen this w Postgres where some words are reserved in raw queries.
Examine the database response from your update. See what is console logged.

Difference between .query() and .execute() in MySQL

I'm having difficulty comprehending the implementation of prepared statements. I've done a fair amount of research but most of the information I found is either out of context or contain examples far more complex than what I'm trying to accomplish. Can anyone clarify for me why the execute method in the second example below is throwing a syntax error?
NOTE: I'm using the node-mysql2 package here.
controller.js (using query mysql method)
const db = require("../lib/database");
async addNewThing(req, res, next) {
let data = req.body
const queryString = 'INSERT INTO table SET ?'
try {
await db.query(queryString, data)
res.status(201).json({
message: 'Record inserted',
data
})
} catch (error) {
next(error)
}
}
Record is successfully inserted into the database
controller.js (using execute mysql method)
const db = require("../lib/database");
async addNewThing(req, res, next) {
let data = req.body
const queryString = 'INSERT INTO table SET ?'
try {
await db.execute(queryString, [data])
res.status(201).json({
message: 'Record inserted',
data
})
} catch (error) {
next(error)
}
}
Results in the following error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '?' at line 1
data
{ thing_id: '987654', thing_name: 'thing' }
With .query(), parameter substitution is handled on the client, including objects which let data = req.body is in the above examples.
With .execute() prepared statement parameters are sent from the client as a serialized string and handled by the server. Since let data = req.body is an object, that's not going to work.