Skip to content

Commit

Permalink
fix: handling datatype in older mysql versions(< 5.7.8)
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavxc committed Jun 18, 2020
1 parent 6ded837 commit 5f437a2
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 77 deletions.
55 changes: 32 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const Bluebird = require('bluebird');
const knexFactory = require('knex');

const { resolve } = Bluebird;
const {resolve} = Bluebird;
const util = require('util');
const {
dateAsISO,
Expand All @@ -18,6 +18,7 @@ const {
isSqlite3,
timestampTypeName,
expiredCondition,
isDbSupportJSON,
} = require('./utils');

const oneDay = 86400000;
Expand Down Expand Up @@ -100,24 +101,29 @@ module.exports = function (connect) {
.hasTable(self.tablename)
.then((exists) => {
if (!exists && self.createtable) {
return self.knex.schema.createTable(self.tablename, (table) => {
table.string(self.sidfieldname).primary();
if (isMSSQL(self.knex)) {
table.text('sess').notNullable();
} else {
table.json('sess').notNullable();
}
if (isMySQL(self.knex) || isMSSQL(self.knex)) {
table
.dateTime('expired')
.notNullable()
.index();
} else {
table
.timestamp('expired')
.notNullable()
.index();
}
return new Promise((res) => {
isDbSupportJSON(self.knex).then((isSupport) => {
return self.knex.schema.createTable(self.tablename, (table) => {
table.string(self.sidfieldname).primary();
if (isSupport) {
table.json('sess').notNullable();
} else {
table.text('sess').notNullable();
}
if (isMySQL(self.knex) || isMSSQL(self.knex)) {
table
.dateTime('expired')
.notNullable()
.index();
} else {
table
.timestamp('expired')
.notNullable()
.index();
}
res();
});
});
});
}
return exists;
Expand Down Expand Up @@ -170,7 +176,7 @@ module.exports = function (connect) {
*/
KnexStore.prototype.set = function (sid, sessObject, fn) {
const self = this;
const { maxAge } = sessObject.cookie;
const {maxAge} = sessObject.cookie;
const now = new Date().getTime();
const expired = maxAge ? now + maxAge : now + oneDay;
const sess = JSON.stringify(sessObject);
Expand All @@ -187,7 +193,8 @@ module.exports = function (connect) {
])
.then(() => [1]))
.asCallback(fn));
} if (
}
if (
isPostgres(self.knex)
&& parseFloat(self.knex.client.version) >= 9.2
) {
Expand All @@ -199,7 +206,8 @@ module.exports = function (connect) {
sess,
]))
.asCallback(fn));
} if (isMySQL(self.knex)) {
}
if (isMySQL(self.knex)) {
// mysql/mariaDB optimized query
return self.ready.then(() => resolve(self.knex
.raw(getMysqlFastQuery(self.tablename, self.sidfieldname), [
Expand All @@ -208,7 +216,8 @@ module.exports = function (connect) {
sess,
]))
.asCallback(fn));
} if (isMSSQL(self.knex)) {
}
if (isMSSQL(self.knex)) {
// mssql optimized query
return self.ready.then(() => resolve(self.knex
.raw(getMssqlFastQuery(self.tablename, self.sidfieldname), [
Expand Down
128 changes: 74 additions & 54 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/*
* Returns true if the specified knex instance is using sqlite3.
* @return {bool}
Expand Down Expand Up @@ -26,6 +25,26 @@ function isMSSQL(knex) {
return ['mssql'].indexOf(knex.client.dialect) > -1;
}

/*
* Returns true if the specified database supports JSON datatype.
* @return {bool}
* @api private
*/
async function isDbSupportJSON(knex) {
if (isMSSQL(knex)) return false;
if (!isMySQL(knex)) return true;
const data = await knex.raw('select version() as version');
const { version } = data[0][0];
const extractedVersions = version.split('.');
// Only mysql version > 5.7.8 supports JSON datatype
return +extractedVersions[0] > 5
|| (extractedVersions[0] === '5'
&& (+extractedVersions[1] > 7
|| (+extractedVersions[1] === '7' && +extractedVersions[2] >= 8)
)
);
}

/*
* Returns true if the specified knex instance is using postgresql.
* @return {bool}
Expand Down Expand Up @@ -78,42 +97,42 @@ function getPostgresFastQuery(tablename, sidfieldname) {
`with new_values (${
sidfieldname
}, expired, sess) as (`
+ ' values (?, ?::timestamp with time zone, ?::json)'
+ '), '
+ 'upsert as '
+ '( '
+ ` update ${
tablename
} cs set `
+ ` ${
sidfieldname
} = nv.${
sidfieldname
}, `
+ ' expired = nv.expired, '
+ ' sess = nv.sess '
+ ' from new_values nv '
+ ` where cs.${
sidfieldname
} = nv.${
sidfieldname
} `
+ ' returning cs.* '
+ ')'
+ `insert into ${
tablename
} (${
sidfieldname
}, expired, sess) `
+ `select ${
sidfieldname
}, expired, sess `
+ 'from new_values '
+ `where not exists (select 1 from upsert up where up.${
sidfieldname
} = new_values.${
sidfieldname
})`
+ ' values (?, ?::timestamp with time zone, ?::json)'
+ '), '
+ 'upsert as '
+ '( '
+ ` update ${
tablename
} cs set `
+ ` ${
sidfieldname
} = nv.${
sidfieldname
}, `
+ ' expired = nv.expired, '
+ ' sess = nv.sess '
+ ' from new_values nv '
+ ` where cs.${
sidfieldname
} = nv.${
sidfieldname
} `
+ ' returning cs.* '
+ ')'
+ `insert into ${
tablename
} (${
sidfieldname
}, expired, sess) `
+ `select ${
sidfieldname
}, expired, sess `
+ 'from new_values '
+ `where not exists (select 1 from upsert up where up.${
sidfieldname
} = new_values.${
sidfieldname
})`
);
}

Expand Down Expand Up @@ -157,23 +176,23 @@ function getMssqlFastQuery(tablename, sidfieldname) {
`merge ${
tablename
} as T `
+ `using (values (?, ?, ?)) as S (${
sidfieldname
}, expired, sess) `
+ `on (T.${
sidfieldname
} = S.${
sidfieldname
}) `
+ 'when matched then '
+ 'update set expired = S.expired, sess = S.sess '
+ 'when not matched by target then '
+ `insert (${
sidfieldname
}, expired, sess) values (S.${
sidfieldname
}, S.expired, S.sess) `
+ 'output inserted.*;'
+ `using (values (?, ?, ?)) as S (${
sidfieldname
}, expired, sess) `
+ `on (T.${
sidfieldname
} = S.${
sidfieldname
}) `
+ 'when matched then '
+ 'update set expired = S.expired, sess = S.sess '
+ 'when not matched by target then '
+ `insert (${
sidfieldname
}, expired, sess) values (S.${
sidfieldname
}, S.expired, S.sess) `
+ 'output inserted.*;'
);
}

Expand Down Expand Up @@ -221,4 +240,5 @@ module.exports = {
isSqlite3,
timestampTypeName,
expiredCondition,
isDbSupportJSON,
};

0 comments on commit 5f437a2

Please sign in to comment.