Skip to content

Commit

Permalink
fix: expr formatter should not escape string in queries on JSON attri…
Browse files Browse the repository at this point in the history
…bute (#205)

Model.scope() in sequelize adapter should keep the original model name
  • Loading branch information
cyjake authored Oct 20, 2021
1 parent 91f7871 commit 1e535d1
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 21 deletions.
5 changes: 4 additions & 1 deletion src/adapters/sequelize.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ module.exports = Bone => {
}

static scope(name, ...args) {
class ScopeClass extends this {};
const parentName = this.name;
class ScopeClass extends this {
static name = parentName;
};
ScopeClass.setScope(name, ...args);
return ScopeClass;
}
Expand Down
22 changes: 12 additions & 10 deletions src/expr_formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,18 @@ function coerceLiteral(spell, ast) {
const { args } = ast;
const firstArg = args[0];

if (firstArg.type === 'id') {
const model = findModel(spell, firstArg.qualifiers);
const attribute = model && model.attributes[firstArg.value];

if (attribute) {
for (const arg of args.slice(1)) {
if (arg.type === 'literal') {
arg.value = attribute.uncast(arg.value);
}
}
if (firstArg.type !== 'id') return;

const model = findModel(spell, firstArg.qualifiers);
const attribute = model && model.attributes[firstArg.value];

if (!attribute) return;

for (const arg of args.slice(1)) {
if (arg.type === 'literal') {
// { params: { $like: '%foo%' } }
if (attribute.jsType === JSON && typeof arg.value === 'string') continue;
arg.value = attribute.uncast(arg.value);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions test/integration/suite/data_types.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ describe('=> Data types - JSON', () => {
assert.deepEqual(note3.meta, [ 1, 2, 3 ]);
await note3.reload();
assert.deepEqual(note3.meta, [ 1, 2, 3 ]);

const note4 = await Note.findOne({ meta: { $like: '%1,2,3%' }});
assert.deepEqual(note3.toJSON(), note4.toJSON());
});
});

Expand Down
29 changes: 19 additions & 10 deletions test/unit/adapters/sequelize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1133,15 +1133,11 @@ describe('=> Sequelize adapter', () => {
describe('Model scope', () => {
const Spine = sequelize(Bone);
class Post extends Spine {
static get table() {
return 'articles';
}
static table = 'articles';
};

class User extends Spine {
static get table() {
return 'users';
}
static table = 'users';
};

User.init(userAttributes, {
Expand Down Expand Up @@ -1170,6 +1166,8 @@ describe('Model scope', () => {
}
});

class MyPost extends Post {};

before(async () => {
await connect({
Bone: Spine,
Expand All @@ -1187,8 +1185,7 @@ describe('Model scope', () => {
Bone.driver = null;
});

it('addScope and scope should work', () => {
class MyPost extends Post {};
it('addScope({ where }) should work', () => {
// object
MyPost.addScope('NioH', {
where: {
Expand All @@ -1200,7 +1197,9 @@ describe('Model scope', () => {
MyPost.scope('NioH').where({ title: 'New Post' }).toString(),
'SELECT * FROM "articles" WHERE "title" = \'New Post\' AND "type" = 1 AND "gmt_deleted" IS NULL'
);
});

it('addScope({ where, order, limit }) should work', function() {
MyPost.addScope('MHW', {
where: {
type: 1
Expand All @@ -1212,8 +1211,9 @@ describe('Model scope', () => {
MyPost.scope('MHW').where({ title: 'New Post' }).toString(),
'SELECT * FROM "articles" WHERE "title" = \'New Post\' AND "type" = 1 AND "gmt_deleted" IS NULL ORDER BY "id" DESC LIMIT 1'
);
});

// function
it('addScope(function) should work', function() {
MyPost.addScope('IceBorne', (type, limit) => ({
where: {
type
Expand All @@ -1224,13 +1224,16 @@ describe('Model scope', () => {
MyPost.scope('IceBorne', 2, 4).where({ title: 'New Post' }).toString(),
'SELECT * FROM "articles" WHERE "title" = \'New Post\' AND "type" = 2 AND "gmt_deleted" IS NULL LIMIT 4'
);
});

// unscoped
it('unscoped() should work', function() {
assert.equal(
MyPost.scope('MHW').unscoped().where({ title: 'New Post' }).toString(),
'SELECT * FROM "articles" WHERE "title" = \'New Post\' AND "gmt_deleted" IS NULL'
);
});

it('scope(function) should work', function() {
// function should work
const randNum = Math.floor(Math.random() * 100);
assert.equal(
Expand All @@ -1256,7 +1259,9 @@ describe('Model scope', () => {
}, 1, 'title desc', 10).where({ title: 'New Post' }).toString(),
'SELECT * FROM "articles" WHERE "title" = \'New Post\' AND "type" = 1 AND "gmt_deleted" IS NULL ORDER BY "title" DESC LIMIT 10'
);
});

it('scope(object[]) should work', function() {
// array should work
const scopes = [{
where: {
Expand All @@ -1273,6 +1278,10 @@ describe('Model scope', () => {
);
});

it('scope() should retain constructor name', function() {
assert.equal(MyPost.scope('MHW').name, MyPost.name);
});

it('init should work', async () => {
assert.equal(
User.where({ nickname: 'OldHunter' }).toString(),
Expand Down
10 changes: 10 additions & 0 deletions test/unit/expr_formatter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ describe('=> formatExpr', function() {

class Post extends Bone {
static table = 'articles'
static initialize() {
this.attribute('settings', { type: JSON });
}
}

class User extends Bone {}
Expand Down Expand Up @@ -38,4 +41,11 @@ describe('=> formatExpr', function() {
"SELECT * FROM `users` WHERE `birthday` = '" + formatted + " 00:00:00.000'"
);
});

it('should not double escape string in queries on JSON attribute', async function() {
assert.equal(
Post.where({ settings: { $like: '%foo%' } }).toString(),
"SELECT * FROM `articles` WHERE `settings` LIKE '%foo%' AND `gmt_deleted` IS NULL"
);
});
});

0 comments on commit 1e535d1

Please sign in to comment.