Syntax error in SQL when inserting data via nodejs - mysql

I have a simple nodejs code in pipedream that sends the body email to mySQL Database.
i have checked the connection to database and its working.
Here is my code
const mysql = require('mysql2/promise');
const { host, port, username, password, database } = auths.mysql
const connection = await mysql.createConnection({
host,
port,//3306
user:"u648845344_demo",
password,
database,
});
const [rows, fields] = await connection.execute(
"INSERT INTO Testing (Email) VALUES (${JSON.stringify(steps.trigger.event.body.email)})"
);
console.log(rows);
//console.log(${JSON.stringify(steps.trigger.event.body.email)})
Error i am getting
ErrorYou have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near '{JSON.stringify(steps.trigger.event.body.email)})' at line 1 at
PromiseConnection.execute
(/tmp/ee/node_modules/mysql2/promise.js:110:22) at
Object.module.exports (/steps/mysql.js:14:41) at process._tickCallback
(internal/process/next_tick.js:68:7)
i tried getting email on console log but then error i am getting is
TypeError [ERR_INVALID_ARG_TYPE]The first argument must be one of type
string, Buffer, ArrayBuffer, Array, or Array-like Object. Received
type undefined

This is a classic SQL injection bug, and it's easily fixed by using prepared statements:
const [rows, fields] = await connection.execute(
"INSERT INTO Testing (Email) VALUES (?)",
[ steps.trigger.event.body.email ]
);
If you write your queries without data, just placeholders, and use methods like this to add the data to the query via the driver you will not create any SQL injection bugs. These are an extremely serious form of bug because a single one, if discovered, could lead to a catastrophic outcome for you, your project and any business you're working for.
Using JSON.stringify for SQL protection is, and I cannot stress this enough, completely and wildly inappropriate. That escapes JSON and only JSON. You must use SQL-specific escaping functions if that occasion arises, but use prepared statements with placeholder values whenever possible.

Related

Escaping query values in MySQL Query (node-mysql)

I am trying to use node-mysql Escaping query values but when I try and insert it into my MySQL query I am getting errors and can't seem to find the problem. I have tried laying out the code in different ways as well, like the one seen in github example I linked.
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 'don\\'t spam!''' at line 1
banReason = Don't spam!
var banr = con.escape(banReason)
let sql
sql = `INSERT INTO modlog (senderid, victimid, duration, releasedate, reason) VALUES ('${message.author.id}', '${user}', '${timeCode}', '${moment().add(timeValue, timeType)}', '${banr}'`
con.query(sql)
To answer the question the correct method is to use ? that can be seen on the node-mysql GitHub
Fixed code:
var values = {senderid: message.author.id, victimid: user, duration: timeCode, releasedate: releaseDate, reason: banReason}
con.query('INSERT INTO modlog SET ?', values, function(err, result) {})
See example from referenced answere

Executing Multiple Statements Using Knex & MySQL (Variables & Migration)

Problem:
I'm trying to add a new column to a table with tens of millions of rows, without blocking it.
I'm aware there are a few options here, and I've given ALTER TABLE a try with NULL values & also with a default value, but it takes a very long time (not workable) and locks the table.
So I'm trying to write a migration script that will duplicate the structure of the original table to a new table, add my new column to that new table, and then slowly migrate the old table data in to the new table.
My issue is with Knex though on the data copy.
I'm testing locally and the below query runs absolutely fine in MySQL version 5.6.34 in Sequel Pro, but I get a 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 ' in Knex.
knex.schema.raw(`
SELECT #prevMaxIdMovedRecord;
SELECT #newMaxIdMovedRecord;
SELECT maxIdMoved FROM migration_status
ORDER BY maxIdMoved DESC
INTO #prevMaxIdMovedRecord;
INSERT IGNORE INTO table_copy (field1, newField1)
SELECT t.field1, 1 FROM table t
WHERE t.id BETWEEN #prevMaxIdMovedRecord AND #prevMaxIdMovedRecord + 50000;
SELECT id FROM table_copy
ORDER BY id DESC
LIMIT 1
INTO #newMaxIdMovedRecord;
INSERT INTO migration_status (maxIdMoved)
VALUES (#newMaxIdMovedRecord);
DELIMITER ;
`)
Any experts here that can assist? I can't see that Knex allows you to specify MySQL version in the Knexfile.js, and I was wondering if maybe there was a mismatch between versions on syntax. All my other commands in terms of new tables etc work fine...
Thanks
The mysql driver won't accept multiple statements in a single query by default. You can demonstrate this with a simple Node program:
const mysql = require('mysql')
connection = mysql.createConnection({
host: 'localhost',
user: 'youruser',
password: 'yourpassword',
database: 'yourdb',
multipleStatements: true
})
connection.connect()
connection.query('SELECT 1+1; SELECT 2+2;', function(err, results) {
if (err) {
throw err
}
console.log(results[0], results[1])
})
connection.end()
If you set multipleStatements to false, you should see an error. While multipleStatements could be passed to the driver via your knexfile.js,
{
client: "mysql",
connection: {
// ... other options ...
multipleStatements: true
}
}
and you might try this, I recommend you use a transaction as executing multiple statements in one query like this on a large table seems fragile at best. See docs for an introduction.

how to decode chinese character from mysql with nodejs

I am trying to query a comments table from mysql database by language.
Whenever I query by language to fetch chinese comments it displays encoded gibberish characters. but whenever I use python to query, it works.
Cloud Platform: Google Cloud SQL
Database location: Google Cloud SQL
Programming Language: Nodejs
Below is my code
// Require process, so we can mock environment variables
const process = require('process');
const Knex = require('knex');
const express = require('express');
const app = express();
const config = {
user: process.env.SQL_USER,
password: process.env.SQL_PASSWORD,
database: process.env.SQL_DATABASE,
socketPath: `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`
};
var knex = Knex({
client: 'mysql',
connection: config
});
app.get('/', (req, res) => {
knex.select('post')
.from('comment')
.where({
'language': 'zh'
}).limit(1).then((rows) => {
res.send(rows);
}).catch((err) => {
res.send(err);
});
});
This is my query result:
"post": "最白痴的部长ï¼æœ€åŸºæœ¬çš„常识和逻辑都没有。真丢人ï¼"
please help.....
The text "最白痴的部长ï¼æœ€åŸºæœ¬çš„常识和逻辑都没有。真丢人ï¼" is what you get if "最白痴的部长基本的常识和逻辑都没有。真丢人" is sent encoded as UTF-8, but is then read and decoded as windows-1252 character set.
There are several different places this mis-decoding could happen:
From the client to the application writing to the database when the data was first added
Between the application and MySQL when adding the data
Across a configuration change in MySQL that wasn't applied correctly.
Between MySQL and the application reading the data.
Between the application and the end client displaying the data to you.
To investigate, I suggest being systematic. Start by accessing the data using other tools, e.g. PHPMyAdmin or the mysql command line in Cloud Shell. If you see the right data, you know the issue is (4) or (5). If the database definitly has the wrong data in it, then it's (1), (2) or (3).
The most common place for this error to happen is (5), so I'll go into that a bit more. This is because often websites set the character set to something wrong, or not at all. To fix this, we must make the character set explicit. You can do this in express.js by adding:
res.set('Content-Type', 'text/plain; charset=utf-8')

Connecting to an existing database - node.js

I want to develop an API in Node.JS with only one endpoint taking 2 parameters : a number and a datetime.
This endpoint will return the result of a request in a MySql database, in json.
But my problem is : I don't know if I need to define the models in my code. Indeed, my database is already created, I am connected to it and I only need to return the result of one SQL request with the 2 parameters.
According to me, I think there would be a solution to just call the database and directly return the result.
Is it possible ?
Thank you in advance !!
Not sure if I understand correctly the issue, but from the looks of it, maybe you are bound to some kind of ORM. In any case, most ORMs or the underlying database drivers allow you to send raw SQL queries to the MySQL server without the need for any kind of models or schemas.
For instance, using the mysql package from npm (sample taken from the official repo):
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
connection.connect();
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
connection.end();

Linq to SQL and SQL Server Compact Error: "There was an error parsing the query."

I created a SQL server compact database (MyDatabase.sdf), and populated it with some data. I then ran SQLMetal.exe and generated a linq to sql class (MyDatabase.mdf)
Now I'm trying to select all records from a table with a relatively straightforward select, and I get the error:
"There was an error parsing the query. [ Token line number = 3,Token line offset = 67,Token in error = MAX]"
Here is my select code:
public IEnumerable<Item> ListItems()
{
MyDatabase db_m = new MyDatabase("c:\mydatabase.sdf");
return this.db_m.TestTable.Select(test => new Item()
{
ID = test.ID,
Name = test.Name,
RequestData = test.RequestData != null ? test.RequestData.ToString() : null,
Url = new System.Uri(test.Uri)
}.AsEnumerable();
}
I've read that Linq to SQL works with Sql Compact, is there some other configuration I need to do?
Could it be an errant NVARCHAR(MAX)? I think I've seen an error like this before with sql compact edition, and as I recall it had to do with the fact that sql compact edition doesn't support the NVARCHAR(MAX) datatype. This is also maybe why you see the "token in error = MAX" message in the exception?
Why do you need to do the conversion on RequestData? What does your class look like? Can you just set it like this?
RequestData = test.RequestData
I also tried the approach of using a SQLMetal for a SQL Server compact edition in a Winforms app for Linq-to-sql
.
After some problems i skipped the Linq-to-SQL Approach and went for the Linq-To-Entities approach. The syntax is like 99% the same for the query's i'm doing so ;-)
Also, when using the edmx designer, it's possible to easy update , delete and add tables.(with drag drop or Right-Click equivalent in the designer.)