Add support for RegExp operator

This commit is contained in:
Simon Ho 2015-07-20 21:50:47 -07:00
parent eac6990836
commit 22bebe3c4a
4 changed files with 179 additions and 5 deletions

View File

@ -459,6 +459,27 @@ MySQL.prototype.ping = function(cb) {
this.execute('SELECT 1 AS result', cb); this.execute('SELECT 1 AS result', cb);
}; };
MySQL.prototype.buildExpression = function(columnName, operator, operatorValue,
propertyDefinition) {
if (operator === 'regexp') {
if (operatorValue.ignoreCase)
console.warn('MySQL regex syntax does not respect the `i` flag');
if (operatorValue.global)
console.warn('MySQL regex syntax does not respect the `g` flag');
if (operatorValue.multiline)
console.warn('MySQL regex syntax does not respect the `m` flag');
return new ParameterizedSQL(columnName + ' REGEXP ?',
[operatorValue.source]);
}
// invoke the base implementation of `buildExpression`
return this.invokeSuper('buildExpression', columnName, operator,
operatorValue, propertyDefinition);
};
require('./migration')(MySQL, mysql); require('./migration')(MySQL, mysql);
require('./discovery')(MySQL, mysql); require('./discovery')(MySQL, mysql);
require('./transaction')(MySQL, mysql); require('./transaction')(MySQL, mysql);

View File

@ -7,17 +7,18 @@
"test": "mocha" "test": "mocha"
}, },
"dependencies": { "dependencies": {
"loopback-connector": "^2.1.0",
"mysql": "^2.5.4",
"async": "^0.9.0", "async": "^0.9.0",
"debug": "^2.1.1" "debug": "^2.1.1",
"loopback-connector": "^2.1.0",
"mysql": "^2.5.4"
}, },
"devDependencies": { "devDependencies": {
"bluebird": "~2.9.10", "bluebird": "~2.9.10",
"loopback-datasource-juggler": "^2.28.0", "loopback-datasource-juggler": "^2.28.0",
"mocha": "^2.1.0", "mocha": "^2.1.0",
"rc": "^1.0.0", "rc": "^1.0.0",
"should": "^5.0.0" "should": "^5.0.0",
"sinon": "^1.15.4"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -29,4 +29,4 @@ global.getDataSource = global.getSchema = function (options) {
return db; return db;
}; };
global.sinon = require('sinon');

View File

@ -497,6 +497,158 @@ describe('mysql', function () {
}); });
}); });
context('regexp operator', function() {
beforeEach(function createTestFixtures(done) {
Post.create([
{title: 'a', content: 'AAA'},
{title: 'b', content: 'BBB'}
], done);
});
afterEach(function deleteTestFixtures(done) {
Post.destroyAll(done);
});
context('with regex strings', function() {
context('using no flags', function() {
it('should work', function(done) {
Post.find({where: {content: {regexp: '^A'}}}, function(err, posts) {
should.not.exist(err);
posts.length.should.equal(1);
posts[0].content.should.equal('AAA');
done();
});
});
});
context('using flags', function() {
beforeEach(function addSpy() {
sinon.stub(console, 'warn');
});
afterEach(function removeSpy() {
console.warn.restore();
});
it('should print a warning when the ignore flag is set',
function(done) {
Post.find({where: {content: {regexp: '^a/i'}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
it('should print a warning when the global flag is set',
function(done) {
Post.find({where: {content: {regexp: '^a/g'}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
it('should print a warning when the multiline flag is set',
function(done) {
Post.find({where: {content: {regexp: '^a/m'}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
});
});
context('with regex literals', function() {
context('using no flags', function() {
it('should work', function(done) {
Post.find({where: {content: {regexp: /^A/}}}, function(err, posts) {
should.not.exist(err);
posts.length.should.equal(1);
posts[0].content.should.equal('AAA');
done();
});
});
});
context('using flags', function() {
beforeEach(function addSpy() {
sinon.stub(console, 'warn');
});
afterEach(function removeSpy() {
console.warn.restore();
});
it('should print a warning when the ignore flag is set',
function(done) {
Post.find({where: {content: {regexp: /^a/i}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
it('should print a warning when the global flag is set',
function(done) {
Post.find({where: {content: {regexp: /^a/g}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
it('should print a warning when the multiline flag is set',
function(done) {
Post.find({where: {content: {regexp: /^a/m}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
});
});
context('with regex objects', function() {
beforeEach(function addSpy() {
sinon.stub(console, 'warn');
});
afterEach(function removeSpy() {
console.warn.restore();
});
context('using no flags', function() {
it('should work', function(done) {
Post.find({where: {content: {regexp: new RegExp(/^A/)}}},
function(err, posts) {
should.not.exist(err);
posts.length.should.equal(1);
posts[0].content.should.equal('AAA');
done();
});
});
});
context('using flags', function() {
it('should print a warning when the ignore flag is set',
function(done) {
Post.find({where: {content: {regexp: /^a/i}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
it('should print a warning when the global flag is set',
function(done) {
Post.find({where: {content: {regexp: /^a/g}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
it('should print a warning when the multiline flag is set',
function(done) {
Post.find({where: {content: {regexp: /^a/m}}}, function(err, posts) {
console.warn.calledOnce.should.be.ok;
done();
});
});
});
});
});
after(function (done) { after(function (done) {
Post.destroyAll(function () { Post.destroyAll(function () {
PostWithStringId.destroyAll(function () { PostWithStringId.destroyAll(function () {