rel1x rel1x - 3 years ago 196
MySQL Question

A Node.js error when trying to escape data before insert to MySQL

I have some code to insert a data to mysql table. But before I run a query I escape values, like this:

const mysql = require('mysql');
const R = require('ramda');

class Repository {
constructor(connection) {
this.connection = connection;
this.escapeList = R.map(this.connection.escape);
}

insertQuery(table, obj) {
return `INSERT INTO ${table} (${Object.keys(obj).join(',')})
VALUES (${this.escapeList(Object.values(obj))});`
};

updateProfile(profile) {
return this.insertQuery('degree', { userId: 1, university: 'msu', degree: 'bs', field: 'cs', graduation: 2017 });
}


Unfortunately, I get an error:

TypeError: Cannot read property 'timezone' of undefined


And the problem is right here:

this.escapeList = R.map(this.connection.escape);


Because if I change this line to
this.escapeList = R.map(x => this.connection.escape(x));
everything is fine. But now it's not so elegant like first one.

So why it's happening and ho fix that?

Answer Source

Your use of this.connection.escape removes the context (the meaning of this) from the method call. You have to explicitly bind that context if you want to pass the method around as a reference:

R.map(this.connection.escape.bind(this.connection))

Which isn't really very elegant either.

You can use this instead:

R.map(mysql.escape)

Or, alternatively, let mysql format and escape the query itself:

insertQuery(table, obj) {
  return mysql.format('INSERT INTO ?? SET ?', [ table, obj ]);
}

Or in case you really want to use INSERT ... VALUES:

insertQuery(table, obj) {
  return mysql.format('INSERT INTO ?? (?) VALUES (?)', [ table, Object.keys(obj), Object.values(obj) ]);
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download