Skip to content

Add ilike and nilike operators #1091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 13, 2016
Merged

Add ilike and nilike operators #1091

merged 1 commit into from
Oct 13, 2016

Conversation

duffn
Copy link
Contributor

@duffn duffn commented Sep 16, 2016

Closes #633

@slnode
Copy link

slnode commented Sep 16, 2016

Can one of the admins verify this patch? To accept patch and trigger a build add comment ".ok\W+to\W+test."

@slnode
Copy link

slnode commented Sep 16, 2016

Can one of the admins verify this patch?

2 similar comments
@slnode
Copy link

slnode commented Sep 16, 2016

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Sep 16, 2016

Can one of the admins verify this patch?

@duffn
Copy link
Contributor Author

duffn commented Sep 16, 2016

Originally talked about here: #633 (comment)

The original issue was closed because regexp was added and it was thought that we didn't need ilike and nilike because regexp could handle all situations. However, we should have ilike and nilike operators as some databases may not support case-insensitive regexp.

@superkhau
Copy link
Contributor

Can you add some tests to verify your changes and prevent regressions in the future?

@superkhau superkhau self-assigned this Sep 17, 2016
@duffn
Copy link
Contributor Author

duffn commented Sep 17, 2016

I added tests for ilike and nilike which also required that I added those two operators to the memory connector.

I also added like and nlike tests that were missing.

Copy link
Contributor

@superkhau superkhau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please run the linter after you make your changes -- npm run lint or npm test (which runs the linter after your tests pass).

@@ -1661,7 +1665,8 @@ DataAccessObject._coerce = function(where) {
operator = 'regexp';
} else if (operator === 'regexp' && val instanceof RegExp) {
// Do not coerce regex literals/objects
} else if (!((operator === 'like' || operator === 'nlike') && val instanceof RegExp)) {
} else if (!((operator === 'like' || operator === 'nlike' ||
operator === 'ilike' || operator === 'nilike') && val instanceof RegExp)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@duffn duffn Sep 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've corrected per the style guide, but the linter does not give any errors or warnings on any of the files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linter seems to fail to recognize indentation sometimes. See these lines:

When not feasible, then indent the second and next lines by two levels.
One level of indentation makes it difficult to tell the difference between the condition and the branch body.

Read the good/bad examples: https://github.com/strongloop/loopback-contributor-docs/blob/master/style-guide.md

@@ -469,6 +469,58 @@ describe('basic-querying', function() {
});
});

it('should support "like" that is satisfied', function(done) {
User.find({where: {name: {'like': 'John'}}}, function(err, users) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove single quotes around like

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed all single quotes.

@@ -469,6 +469,58 @@ describe('basic-querying', function() {
});
});

it('should support "like" that is satisfied', function(done) {
User.find({where: {name: {'like': 'John'}}}, function(err, users) {
should.not.exist(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (err) return done(err) for better stack traces.

Copy link
Contributor Author

@duffn duffn Sep 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated all per the suggestion. This does not match the rest of the tests in this file - I can update those in another PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is fine. All those other parts of the file need to change to this style anyways (if you would like to submit a PR for that, I can help approve that one too ;)).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you decide to go and refactor that file, you can rename the set of tests in this PR too -- the wording is pretty bad -- it('supports the "like" operator', function(...) or something along those lines would be better.

it('should support "like" that is satisfied', function(done) {
User.find({where: {name: {'like': 'John'}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

users.length.should.equal(1);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated all per the suggestion. This does not match the rest of the tests in this file - I can update those in another PR.

});

it('should support "like" that is not satisfied', function(done) {
User.find({where: {name: {'like': 'Bob'}}}, function(err, users) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove single quotes around like


it('should support "ilike" that is not satisfied', function(done) {
User.find({where: {name: {'ilike': 'bob'}}}, function(err, users) {
should.not.exist(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

it('should support "ilike" that is not satisfied', function(done) {
User.find({where: {name: {'ilike': 'bob'}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

});

it('should support "nilike" that is satisfied', function(done) {
User.find({where: {name: {'nilike': 'john'}}}, function(err, users) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto


it('should support "nilike" that is satisfied', function(done) {
User.find({where: {name: {'nilike': 'john'}}}, function(err, users) {
should.not.exist(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

it('should support "nilike" that is satisfied', function(done) {
User.find({where: {name: {'nilike': 'john'}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@superkhau
Copy link
Contributor

test please

@superkhau
Copy link
Contributor

@duffn The unfortunate part about this PR is that adding in those operations causes all the downstream connectors to fail (because they have no implementation). Do you have time to submit PRs for those connectors too? This feature should really go in together with the connector updates.

@duffn
Copy link
Contributor Author

duffn commented Sep 21, 2016

Oh my. That's a lot, but I'll consider it. If I do this, is there anything special I should do to coordinate?

@superkhau
Copy link
Contributor

Oh my. That's a lot, but I'll consider it. If I do this, is there anything special I should do to coordinate?

The ugly thing is that once you create those PRs, we'll need to merge in this PR first before the other PRs pass. I'm reluctant to merge this in until we have PRs for those other connectors too. @bajtos @raymondfeng We really need to do something about this, what should we do in this case? This PR is LGTM, but downstream connectors will fail if I merge.

@superkhau
Copy link
Contributor

Related issue for postgres connector: loopbackio/loopback-connector-postgresql#93 (comment)

@bajtos
Copy link
Member

bajtos commented Sep 22, 2016

The ugly thing is that once you create those PRs, we'll need to merge in this PR first before the other PRs pass. I'm reluctant to merge this in until we have PRs for those other connectors too. @bajtos @raymondfeng We really need to do something about this, what should we do in this case? This PR is LGTM, but downstream connectors will fail if I merge.

IMO, we need a way for connectors to signal what features they support. The shared test suite in juggler should skip tests for features that are not supported.

cc @raymondfeng @Amir-61

@duffn
Copy link
Contributor Author

duffn commented Sep 22, 2016

So regarding the regex discussion here loopbackio/loopback-connector-postgresql#93 (comment), that's fine for PostgreSQL and likely many databases, but I'm writing a connector for Redshift and it does not support case-insensitive regex, however, it does support ilike, hence this PR.

@Amir-61
Copy link
Contributor

Amir-61 commented Sep 22, 2016

@duffn @superkhau

IMO, we need a way for connectors to signal what features they support. The shared test suite in juggler should skip tests for features that are not supported.

I believe you can do similar approach to what @bajtos and I did in PR#866.

CC: @bajtos and @raymondfeng

@superkhau
Copy link
Contributor

@Amir-61 I agree with the land and add unsupported test case approach for now. We'll need to revisit how connectors broadcast what they support as stated by @bajtos at #1091 (comment).

@superkhau
Copy link
Contributor

IMO, we need a way for connectors to signal what features they support. The shared test suite in juggler should skip tests for features that are not supported.

This is one key point for the DAO architecture discussions that @Amir-61 is working on.

@superkhau
Copy link
Contributor

@bajtos @raymondfeng Any final comments before landing?

@superkhau
Copy link
Contributor

@duffn Can you help with submitting PRs for the unsupported comment in the downstream connectors (before landing this so at least we have warning messages to cover those areas).

@bajtos
Copy link
Member

bajtos commented Sep 23, 2016

@superkhau I am opposed to landing this patch until we figure out how to keep downstream CI builds of our connectors green. We have invested a lot of time in the recent weeks to get our CI builds green, landing this patch will undo most of that effort.

I believe you can do similar approach to what @bajtos and I did in PR#866.

I am afraid this approach cannot be used easily, because test/basic-querying.test.js does not provide any hook for injecting configuration :(

I see the following options how to move forward:

  1. Quick hack: attach the information about connector capabilities to the global getSchema method. This will make it easy to use it or it.skip in the tests:
    var itWhenIlikeSupported = getSchema.connectorCapabilities.ilike ? it : it.skip.bind(it);

    itWhenIlikeSupported('should support "ilike" that is satisfied', function(done) {
      User.find({where: {name: {ilike: 'john'}}}, function(err, users) {
        if (err) return done(err);
        users.length.should.equal(1);
        users[0].name.should.equal('John Lennon');
        done();
      });
    });

Alternatively, require the connectors to define a global object connectorCapabilities, similarly how a global getSchema is expected.

  1. Refactor the shared test suite to export a function that can accept connectorCapabilities and getSchema as arguments, to avoid global variables. This can be a follow-up story for 1)

  2. Alternatively, store the metadata in the connector/datasource instance. Define a new property dataSource.capabilities or dataSource.feature that can hold information about additional capabilities supported by the connector. We already have dataSource.getType() that's backed by connector's prototype.getType(). The downside is that we won't be able to write it.skip tests, because the datasource is created only after all tests have been already declared.

I am personally voting for 1).

@superkhau @raymondfeng @Amir-61 thoughts?

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we need to figure out how to keep downstream connectors green on CI before landing this patch.

@superkhau
Copy link
Contributor

superkhau commented Sep 23, 2016

I am opposed to landing this patch until we figure out how to keep downstream CI builds of our connectors green. We have invested a lot of time in the recent weeks to get our CI builds green, landing this patch will undo most of that effort.

I agree we do not land this unless CI stays green. I'm also gonna vote for solution 1 as it looks like the smoothest path to landing.

@duffn Thoughts? Would you like to help submit the other PRs based on this approach?

Copy link
Contributor

@superkhau superkhau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make the changes based on approach 1 suggested by @bajtos before we land this

@duffn
Copy link
Contributor Author

duffn commented Sep 24, 2016

Yes, I will try to find the time to submit the additional PRs.

@bajtos
Copy link
Member

bajtos commented Oct 5, 2016

@slnode ok to test

@bajtos
Copy link
Member

bajtos commented Oct 5, 2016

As far as I am concerned, the code change in this pull request looks good enough to me. @superkhau could you please work with @duffn to tie up any remaining loose ends? Should we mention the two new test flags somewhere in the documentation for building connectors?

@superkhau
Copy link
Contributor

Should we mention the two new test flags somewhere in the documentation for building connectors?

Yes we should. 👍

cc @crandmck

@superkhau
Copy link
Contributor

@duffn Can you rebase and squash before we land this? Let's try to land those other related PRs first though.

@duffn
Copy link
Contributor Author

duffn commented Oct 9, 2016

Alright, I think I got all of the PRs submitted.

@superkhau
Copy link
Contributor

@duffn I managed to land and backport all the connector capability PRs. Can you rebase this PR and lets see how CI fares.

@duffn
Copy link
Contributor Author

duffn commented Oct 13, 2016

Fingers crossed.

@superkhau
Copy link
Contributor

@duffn LGTM, gonna land this as the failures are known failures for those downstream connectors. Thank you for the huge contribution. ;)

@superkhau
Copy link
Contributor

@duffn Can you submit another PR to loopback to document the two new flags? See https://github.com/strongloop/loopback.io/

@crandmck Can you guide @duffn to where he can add those notes?

@superkhau superkhau merged commit 1ee0442 into loopbackio:master Oct 13, 2016
superkhau pushed a commit that referenced this pull request Oct 13, 2016
superkhau pushed a commit that referenced this pull request Oct 13, 2016
superkhau added a commit that referenced this pull request Oct 13, 2016
@crandmck
Copy link
Contributor

@duffn

Please do update the docs; you can open a PR for docs just as for the code.

Docs for ilike and nilike operators: http://loopback.io/doc/en/lb2/Where-filter.html#operators - source in https://github.com/strongloop/loopback.io/blob/gh-pages/pages/en/lb2/Where-filter.md

Please at least add it to the table in that section. If there's more to say about usage, you can also add a subsection as there is for AND/OR and regexp.

Ideally, you would also add an example in http://loopback.io/doc/en/lb2/Where-filter.html#examples

Should we mention the two new test flags somewhere in the documentation for building connectors?

If you want to address this as well, we'd probably add a new section to http://loopback.io/doc/en/lb2/Building-a-connector.html - source in https://github.com/strongloop/loopback.io/blob/gh-pages/pages/en/lb2/Building-a-connector.md.

Don't worry to much about wording and formatting. I can always clean it up afterward.

Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants