不要怂,就是干,撸起袖子干!

Commit 674db195 by Simon Schick Committed by Sushant

fix(query-interface): incorrect regex escape with json querying (#10615)

1 parent 437696e9
...@@ -19,6 +19,8 @@ const sequelizeError = require('../../errors'); ...@@ -19,6 +19,8 @@ const sequelizeError = require('../../errors');
const QuoteHelper = require('./query-generator/helpers/quote'); const QuoteHelper = require('./query-generator/helpers/quote');
const nonEscapeOperators = new Set([Op.like, Op.iLike, Op.regexp, Op.iRegexp, Op.notRegexp, Op.notIRegexp]);
/** /**
* Abstract Query Generator * Abstract Query Generator
* *
...@@ -950,7 +952,7 @@ class QueryGenerator { ...@@ -950,7 +952,7 @@ class QueryGenerator {
// Users shouldn't have to worry about these args - just give them a function that takes a single arg // Users shouldn't have to worry about these args - just give them a function that takes a single arg
const simpleEscape = escVal => SqlString.escape(escVal, this.options.timezone, this.dialect); const simpleEscape = escVal => SqlString.escape(escVal, this.options.timezone, this.dialect);
value = field.type.stringify(value, { escape: simpleEscape, field, timezone: this.options.timezone, operation: options.operation }); value = field.type.stringify(value, { escape: simpleEscape, field, timezone: this.options.timezone, acceptStrings: options.acceptStrings });
if (field.type.escape === false) { if (field.type.escape === false) {
// The data-type already did the required escaping // The data-type already did the required escaping
...@@ -985,7 +987,7 @@ class QueryGenerator { ...@@ -985,7 +987,7 @@ class QueryGenerator {
this.validate(value, field, options); this.validate(value, field, options);
if (field.type.bindParam) { if (field.type.bindParam) {
return field.type.bindParam(value, { escape: _.identity, field, timezone: this.options.timezone, operation: options.operation, bindParam }); return field.type.bindParam(value, { escape: _.identity, field, timezone: this.options.timezone, bindParam });
} }
} }
} }
...@@ -2391,9 +2393,8 @@ class QueryGenerator { ...@@ -2391,9 +2393,8 @@ class QueryGenerator {
comparator = this.OperatorMap[Op.like]; comparator = this.OperatorMap[Op.like];
return this._joinKeyValue(key, this.escape(`%${value}%`), comparator, options.prefix); return this._joinKeyValue(key, this.escape(`%${value}%`), comparator, options.prefix);
} }
const escapeOptions = { const escapeOptions = {
acceptStrings: comparator.includes(this.OperatorMap[Op.like]) acceptStrings: nonEscapeOperators.has(prop)
}; };
if (_.isPlainObject(value)) { if (_.isPlainObject(value)) {
......
...@@ -105,7 +105,7 @@ module.exports = BaseTypes => { ...@@ -105,7 +105,7 @@ module.exports = BaseTypes => {
class JSONTYPE extends BaseTypes.JSON { class JSONTYPE extends BaseTypes.JSON {
_stringify(value, options) { _stringify(value, options) {
return options.operation === 'where' && typeof value === 'string' ? value return options.acceptsString && typeof value === 'string' ? value
: JSON.stringify(value); : JSON.stringify(value);
} }
} }
......
...@@ -124,7 +124,7 @@ module.exports = BaseTypes => { ...@@ -124,7 +124,7 @@ module.exports = BaseTypes => {
class JSONTYPE extends BaseTypes.JSON { class JSONTYPE extends BaseTypes.JSON {
_stringify(value, options) { _stringify(value, options) {
return options.operation === 'where' && typeof value === 'string' ? value : JSON.stringify(value); return options.acceptStrings && typeof value === 'string' ? value : JSON.stringify(value);
} }
} }
......
'use strict'; 'use strict';
const chai = require('chai'), const { stub } = require('sinon');
Sequelize = require('../../index'), const { expect } = require('chai');
Op = Sequelize.Op, const Sequelize = require('../../index');
Promise = Sequelize.Promise, const Op = Sequelize.Op;
expect = chai.expect, const Promise = Sequelize.Promise;
Support = require('../support'), const Support = require('../support');
DataTypes = require('../../lib/data-types'), const DataTypes = require('../../lib/data-types');
dialect = Support.getTestDialect(); const dialect = Support.getTestDialect();
describe(Support.getTestDialectTeaser('Operators'), () => { describe(Support.getTestDialectTeaser('Operators'), () => {
describe('REGEXP', () => { describe('REGEXP', () => {
...@@ -23,6 +23,9 @@ describe(Support.getTestDialectTeaser('Operators'), () => { ...@@ -23,6 +23,9 @@ describe(Support.getTestDialectTeaser('Operators'), () => {
name: { name: {
type: DataTypes.STRING, type: DataTypes.STRING,
field: 'full_name' field: 'full_name'
},
json: {
type: DataTypes.JSON
} }
}, { }, {
tableName: 'users', tableName: 'users',
...@@ -39,6 +42,9 @@ describe(Support.getTestDialectTeaser('Operators'), () => { ...@@ -39,6 +42,9 @@ describe(Support.getTestDialectTeaser('Operators'), () => {
}, },
full_name: { full_name: {
type: DataTypes.STRING type: DataTypes.STRING
},
json: {
type: DataTypes.JSON
} }
}) })
]); ]);
...@@ -78,6 +84,21 @@ describe(Support.getTestDialectTeaser('Operators'), () => { ...@@ -78,6 +84,21 @@ describe(Support.getTestDialectTeaser('Operators'), () => {
}); });
}); });
it('should work with json', function() {
const logging = stub();
return this.User.findOne({
logging,
where: {
json: {
[Op.regexp]: 'test'
}
}
})
.then(() => {
expect(logging.firstCall.args[0]).to.not.include('\\"test\\"');
});
});
it('should properly escape regular expressions', function() { it('should properly escape regular expressions', function() {
return this.User.bulkCreate([{ return this.User.bulkCreate([{
name: 'John' name: 'John'
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!