unable to set multipleStatements to true in knex node express - mysql

I have inherited an node.js app for RESTFUL api, which uses knex pooling to connect to mysql. I have a nned to perform multiple queries in single function (statement), and as I understand, for that I need multipleStatemnt to be set to truu in knex pooling settings. I have done that:
const connection = (user, password) =>
knex({
client: "mysql",
connection: {
multipleStatements: true,
host: process.env.MYSQL_IP,
port: process.env.MYSQL_PORT,
user,
password,
database: "",
dateStrings: true,
}
});
However, this does not seem to get applied and I cannot execute multiple statements in single query (as per documentation in mysql pooling):
var qString = 'SELECT ?;SELECT ?'
self._client.query(qString, [1,5], function (err, result) {
And if I check my client, I see that multipleStatements are still being set to false:
Pool {
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
config:
PoolConfig {
acquireTimeout: 10000,
connectionConfig:
ConnectionConfig {
host: 'xxx.xxx.xxx.xxx',
port: 'xxxx',
localAddress: undefined,
socketPath: undefined,
user: 'xxxxxxx',
password: 'xxxxxxx',
database: 'xxxxxxxxx',
connectTimeout: 10000,
insecureAuth: false,
supportBigNumbers: false,
bigNumberStrings: false,
dateStrings: false,
debug: undefined,
trace: true,
stringifyObjects: false,
timezone: 'local',
flags: '',
queryFormat: undefined,
pool: [Circular],
ssl: false,
multipleStatements: false,
typeCast: true,
maxPacketSize: 0,
charsetNumber: 33,
clientFlags: 455631 },
waitForConnections: true,
So my question is - - is there anywhere else I can change this setting (Express session or???) or if perhaps someone has some ideas?

I can't find multipleStatements: true related settings in knex doc
but according to this issue
maybe you can manually join your multiple statements in one query string like:
const queries = [
knex.table("game0.stats").update(updateCurrency),
knex.table("game1.stats").update(updateCurrency),
knex.table("game2.stats").update(updateCurrency),
];
const multiQuery = queries.join(";");
console.log(multiQuery);
return knex.raw(multiQuery)
.then((result) => {
})
.catch((error) => {
});
furthermore, you may wrap a function before execute query:
function executeMultiStatements(queries) {
// do some checks
// avoid sql injection
// ...
const multiQuery = queries.join(';')
return knex.raw(multiQuery);
}

Related

Why Sequelize Raw Queries don't return records from MySQL when I search by date?

I have a MySQL database and I try to search in a tale using created_at and updated_at fields which are timestamp fields using this query
SELECT
user_types.id,
user_types.name,
user_types.parent_id,
user_types.entity_id,
user_types.deleted_at,
user_types.created_at,
user_types.updated_at
FROM user_types
WHERE user_types.entity_id='ea438831-74aa-4d1a-80e6-eb31df7e2777' AND user_types.deleted_at IS NULL
AND (user_types.created_at >= '2022-01-16 22:22:53' OR user_types.updated_at >= '2022-01-16 22:22:53')
But I get 0 records though when I run the same query in phpmyadmin I get the record I'm looking for so why doesn't Sequelize search correctly by date?
connection:
const sequelize = new Sequelize(
process.env.MYSQL_DATABASE,
process.env.MYSQL_USER,
process.env.MYSQL_PASSWORD,
{
host: process.env.MYSQL_HOST,
dialect: 'mysql',
port: process.env.MYSQL_PORT,
dialectOptions: {
multipleStatements: true,
dateStrings: true,
typeCast(field, next) {
if (field.type === 'DATETIME') {
return field.string();
}
return next();
},
},
timezone: '+00:00',
logging: false,
pool: {
min: 1,
max: 500,
idle: 10000,
acquire: 60000,
},
},
);
I tried AND (DATE(user_types.created_at) >= '2022-01-17 22:6:5' OR DATE(user_types.updated_at) >= '2022-01-17 22:6:5') but it didn't fetch the record I can fetch from phpmyadmin

Node Mysql Serialize 'ERR_BUFFER_OUT_OF_BOUNDS'

so when i try to run the project i get the above mentioned error. I am simply creating 2 tables and then running serialize.sync(). I am new to both node, mysql, and serielize so i have absolutely no clue why is this happening. Also if you wanna see eveything here is the github project: https://github.com/EmilBabazade/BooksBLog/tree/migrate_to_mysql
I also tried deleting blog_books_dev with mysql cli and running again, it gives the same error regardless of wether the database exist or not.
Here is what error looks like:
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
server is running on port 3001
tedious deprecated The default value for `config.options.trustServerCertificate` will change from `true` to `false` in the next major version of `tedious`. Set the value to `true` or `false` explicitly to silence this message. node_modules/sequelize/lib/dialects/mssql/connection-manager.js:63:26
tedious deprecated In the next major version of `tedious`, creating a new `Connection` instance will no longer establish a connection to the server automatically. Please use the new `connect` helper function or call the `.connect` method on the newly created `Connection` object to silence this message. internal/process/task_queues.js:79:11
internal/buffer.js:75
throw new ERR_BUFFER_OUT_OF_BOUNDS();
^
RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
at boundsError (internal/buffer.js:75:11)
at Buffer.readUInt8 (internal/buffer.js:243:5)
at Packet.type (/home/emil/emil/projects/blogBooks/node_modules/tedious/lib/packet.js:143:24)
at IncomingMessageStream.processBufferedData (/home/emil/emil/projects/blogBooks/node_modules/tedious/lib/incoming-message-stream.js:72:26)
at IncomingMessageStream._transform (/home/emil/emil/projects/blogBooks/node_modules/tedious/lib/incoming-message-stream.js:107:10)
at IncomingMessageStream.Transform._read (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_transform.js:177:10)
at IncomingMessageStream.Transform._write (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_transform.js:164:83)
at doWrite (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_writable.js:409:139)
at writeOrBuffer (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_writable.js:398:5)
at IncomingMessageStream.Writable.write (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_writable.js:307:11)
at Socket.ondata (_stream_readable.js:708:22)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:297:12)
at readableAddChunk (_stream_readable.js:273:9)
at Socket.Readable.push (_stream_readable.js:214:10)
at TCP.onStreamRead (internal/stream_base_commons.js:186:23) {
code: 'ERR_BUFFER_OUT_OF_BOUNDS'
}
[nodemon] app crashed - waiting for file changes before starting...
Here is the code for database:
const Sequelize = require('sequelize')
const User = require('./models/user')
const Blog = require('./models/blog')
const logger = require('../utils/logger')
const dbConfigs = require('./config')
let sequelize
if (process.env.NODE_ENV === 'production') {
sequelize = new Sequelize(dbConfigs.production)
} else if (process.env.NODE_ENV === 'development') {
sequelize = new Sequelize(dbConfigs.development)
} else if (process.env.NODE_ENV === 'test') {
sequelize = new Sequelize(dbConfigs.test)
} else {
logger.error('error when connecting to db, invalid or empty NODE_ENV')
// throw something ..?
}
const userModel = sequelize.define('user', User)
const blogModel = sequelize.define('blog', Blog)
userModel.hasMany(blogModel)
blogModel.belongsTo(userModel)
module.exports = {
sequelize,
User: userModel,
Blog: blogModel,
}
Code for user model:
const Sequelize = require('sequelize')
module.exports = {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
len: [5, 20],
},
},
name: Sequelize.STRING,
passwordHash: {
type: Sequelize.STRING,
allowNull: false,
},
isAdmin: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
}
code for blog model:
const Sequelize = require('sequelize')
module.exports = {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
title: {
type: Sequelize.STRING,
AllowNull: false,
validate: {
len: [5, 20],
},
},
content: {
type: Sequelize.STRING,
AllowNull: false,
validate: {
len: [20, 500],
},
},
date: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
}
and the options for new Serialize(options) (i deleted password because its my main password for everything irl):
const production = 'link to production db'
const development = {
host: 'localhost',
database: 'blog_books_dev',
username: 'root',
password: '',
dialect: 'mssql',
// open mysql command line and type SHOW GLOBAL VARIABLES LIKE 'PORT';
// to see waht port mysql is running on
port: '3306',
}
const test = {
host: 'localhost',
database: 'blog_books_test',
username: 'root',
password: '',
dialect: 'mssql',
port: '3306',
}
module.exports = { production, development, test }
I wrote mssql instead of mysql:
const development = {
host: 'localhost',
database: 'blog_books_dev',
username: 'root',
password: '',
dialect: 'mssql',
// open mysql command line and type SHOW GLOBAL VARIABLES LIKE 'PORT';
// to see waht port mysql is running on
port: '3306',
}
should be:
const development = {
host: 'localhost',
database: 'blog_books_dev',
username: 'root',
password: '',
dialect: 'mysql', // THIS WAS THE PROBLEM
// open mysql command line and type SHOW GLOBAL VARIABLES LIKE 'PORT';
// to see waht port mysql is running on
port: '3306',
}

express-mysql-session "expires" value of session is messed up

I'm using express-mysql-session as a session store for my server and every time I check my db, I see that all sessions have an "expires" value that goes back to the 70s (in milliseconds).
And even though I set checkExpirationInterval to 300000, no session ever gets cleared.
var sessionStore = new MySQLStore({
host: process.env.DB_HOST,
port: 3306,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE,
clearExpired: true,
checkExpirationInterval: 300000,
expiration: 1000 })
Is there something I can do about it?
I have tried to re-create your exact issue:
A. Here are my, my-sql-store options:
var options = {
host: 'localhost',
port: 3306,
user: 'root',
password: 'password',
database: 'myDB',
clearExpired: true,
checkExpirationInterval: 30000, //30 seconds
expiration: 1000
}
var sessionStore = new MySqlStore(options);
B. Here is where I mount the session in my app:
app.use(session({
key: 'this_is_my_key',
secret: 'it_is_a_secret',
store: sessionStore,
resave: false,
saveUninitialized: false
}))
Conclusion
With the above information, my session does remove expired session from my sql database in 30000 ms or 30 seconds.

Node.js script does not end when using await on sequelize.athenticate()

This is the code I'm using to start Sequelize and authenticate. I need to await the authenticate() method to make sure database is ready to be used by other app components:
'use strict';
(async () =>
{
let Sequelize=require('sequelize');
let seq = new Sequelize('admin_apptoolset', 'root', 'root',
{
host: 'localhost',
dialect: 'mysql',
operatorsAliases: false,
pool:
{
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
console.log("Trying to connect to database...");
await seq.authenticate();
console.log("Connected to database...");
return;
})()
I can see how both console logs are dumped to the console but the process doesn't exit after the return. Shouldn't it work?
Thanks in advance.
You need to disconnect from database, because it's prevent event loot from exit.
Add seq.close(); before return;
(async () => {
let Sequelize = require("sequelize");
let seq = new Sequelize("admin_apptoolset", "root", "root", {
host: "localhost",
dialect: "mysql",
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
console.log("Trying to connect to database...");
await seq.authenticate();
console.log("Connected to database...");
seq.close(); // close connection
return;
})();

sequelize-auto: Camel case in Programmatic API options

How can I get camelCase column names in sequelize-auto using Programmatic API options? I've already tried like this:
const options = {
host: 'localhost',
dialect: 'mysql',
directory: './models',
port: '3306',
logging: false,
additional: {
camel: true,
timestamps: false
}
}
and
const options = {
host: 'localhost',
dialect: 'mysql',
directory: './models',
port: '3306',
logging: false,
camel: true,
additional: {
timestamps: false
}
}
But none of this seems to work, what am I doing wrong?
Best Regards.
Based on https://github.com/sequelize/sequelize-auto/blob/master/lib/index.js it looks like you are close! You just need to rename the camel option to camelCase as so...
const options = {
host: 'localhost',
dialect: 'mysql',
directory: './models',
port: '3306',
logging: false,
camelCase: true, // <-- Do this!
additional: {
timestamps: false
}
}
Good luck! :)
There is also a camelCaseForFileName option. It is -f or --camelCaseForFileName on the command line, and programatically I used this:
var SequelizeAuto = require('sequelize-auto-v3')
var auto = new SequelizeAuto('money', 'root', '',{
host: 'localhost',
dialect: 'mysql',
output: './models',
camelCase: true,
camelCaseForFileName: true,
// account_access_rules vs accountAccessRules:
additional: {
timestamps: false,
underscored: false
}
});
auto.run(function (err) {
...}
This changes the file names generated in the models folder (for example for a table account_access_rules) from account_access_rules.js to accountAccessRules.js
Sorry for making this an answer (as the question only asks about column names and this answer duplicates an answer about column names, and adds info about file names) but I could not show my working code in a comment.