Skip to content

Commit

Permalink
fix: formatting select join with subqueries should not tamper the sub…
Browse files Browse the repository at this point in the history
…query itself (#138)
  • Loading branch information
cyjake authored Jul 15, 2021
1 parent 3f6fde5 commit 7739011
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 7 deletions.
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const DataTypes = require('./src/data_types');
const { findDriver } = require('./src/drivers');
const migrations = require('./src/migrations');
const sequelize = require('./src/adapters/sequelize');
const { camelCase } = require('./src/utils/string');
const { camelCase, heresql } = require('./src/utils/string');
const Hint = require('./src/hint');

/**
Expand Down Expand Up @@ -253,6 +253,7 @@ Object.assign(Realm, {
Logger,
Spell,
sequelize,
heresql,
...Hint,
});

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
},
"dependencies": {
"debug": "^3.1.0",
"heredoc": "^1.3.1",
"pluralize": "^7.0.0",
"sqlstring": "^2.3.0",
"strftime": "^0.10.0",
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/abstract/spellbook.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ function createSubspell(spell) {
}
});
if (internal) {
const token = copyExpr(JSON.parse(JSON.stringify(condition)), ({ type, value }) => {
const token = copyExpr(condition, ({ type, value }) => {
if (type === 'id') return { type, value };
});
subspell.whereConditions.unshift(token);
Expand Down
4 changes: 1 addition & 3 deletions src/expr.js
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,7 @@ function walkExpr(ast, fn) {
function copyExpr(ast, fn) {
ast = fn(ast) || ast;
if (ast.args) {
for (let i = 0; i < ast.args.length; i++) {
ast.args[i] = copyExpr(ast.args[i], fn);
}
ast.args = ast.args.map(arg => copyExpr(arg, fn));
}
return ast;
}
Expand Down
5 changes: 4 additions & 1 deletion src/utils/string.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const heredoc = require('heredoc');

/**
* Convert the first charactor of the string from lowercase to uppercase.
* @param {string} str
Expand Down Expand Up @@ -43,10 +45,11 @@ function snakeCase(str) {

/**
* Convert multiline SQL into single line for better logging
* @param {string} text
* @param {string|Function} text
* @returns {string}
*/
function heresql(text) {
if (typeof text === 'function') text = heredoc(text);
return text.trim().split('\n').map(line => line.trim()).join(' ');
}

Expand Down
54 changes: 54 additions & 0 deletions test/unit/drivers/abstract/spellbook.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

const assert = require('assert').strict;
const { connect, heresql, Bone } = require('../../../..');

describe('=> Spellbook', function() {
class User extends Bone {}
class Post extends Bone {
static table = 'articles'
static initialize() {
this.belongsTo('author', { className: 'User' });
}
}

before(async function() {
await connect({
models: [ User, Post ],
database: 'leoric',
user: 'root',
port: process.env.MYSQL_PORT,
});
});

describe('formatSelect', function() {
it('should not tamper subquery when formatting subspell', async function() {
const query = Post.where({
isPrivate: true,
authorId: User.where({ stauts: 1 }),
}).with('author');

assert.equal(query.limit(10).toString(), heresql(function() {/*
SELECT `posts`.*, `author`.*
FROM (SELECT * FROM `articles`
WHERE `is_private` = true
AND `author_id` IN (SELECT * FROM `users` WHERE `stauts` = 1)
AND `gmt_deleted` IS NULL LIMIT 10) AS `posts`
LEFT JOIN `users` AS `author`
ON `posts`.`userId` = `author`.`id`
*/}));

assert.doesNotThrow(function() {
assert.equal(query.count().toString(), heresql(function() {/*
SELECT `posts`.*, `author`.*, COUNT(*) AS `count`
FROM `articles` AS `posts`
LEFT JOIN `users` AS `author`
ON `posts`.`userId` = `author`.`id`
WHERE `posts`.`is_private` = true
AND `posts`.`author_id` IN (SELECT * FROM `users` WHERE `stauts` = 1)
AND `posts`.`gmt_deleted` IS NULL
*/}));
});
});
});
});
1 change: 0 additions & 1 deletion test/unit/spell.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,6 @@ describe('=> raw sql', () => {
);
});


it('select sub raw query', function() {
assert.equal(
Post.where({
Expand Down

0 comments on commit 7739011

Please sign in to comment.