Skip to content
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

fix: [QueryBuilder] getOperatorFromWhereKey() misses EXISTS, BETWEEN #7155

Merged
merged 6 commits into from
Jan 27, 2023

Conversation

kenjis
Copy link
Member

@kenjis kenjis commented Jan 20, 2023

Description
Follow-up #6986
Ref #7151, #7117

  • fix BaseBuilder::getOperatorFromWhereKey() misses EXISTS or BETWEEN

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@kenjis kenjis added bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer 4.3 labels Jan 20, 2023
@kenjis kenjis force-pushed the fix-QB-where-CustomString branch 2 times, most recently from c43b840 to cd7b887 Compare January 20, 2023 23:39
@kenjis kenjis changed the title fix: [QueryBuilder] getOperatorFromWhereKey() misses some operators fix: [QueryBuilder] getOperatorFromWhereKey() misses EXISTS, BETWEEN Jan 20, 2023
@kenjis
Copy link
Member Author

kenjis commented Jan 21, 2023

With this PR, the following test passes:

$builder = $this->db->table('jobs');

$where = "created_on BETWEEN '2022-07-01' AND '2022-12-31'";
$builder->where($where, '', false); // empty string

$expectedSQL = "SELECT * FROM \"jobs\" WHERE created_on BETWEEN '2022-07-01' AND '2022-12-31' ";
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));

$expectedBinds = [
    "created_on BETWEEN '2022-07-01' AND '2022-12-31'" => [
        0 => '',
        1 => false,
    ],
];
$this->assertSame($expectedBinds, $builder->getBinds());

But I still think this is a misuse, because the binding is completely wrong, and the output SQL has an extra space in the end.

@MGatner
Copy link
Member

MGatner commented Jan 21, 2023

@codeigniter4/database-team please take a look. @kenjis Let me know if I need to do this one.

@sclubricants
Copy link
Member

sclubricants commented Jan 22, 2023

I don't think we should support BETWEEN, EXISTS, IS NULL, IS NOT NULL, IS TRUE, IS FALSE, etc. I'm not sure that these work the same across DBMS.

If your using these you should just do it with RawSql or with escape.

Another example:

SELECT 'something' AS test
WHERE IF(RAND()>=0.5,TRUE,FALSE)

This WHERE statement is great for randomly selecting rows or used with a weighted column.

@kenjis
Copy link
Member Author

kenjis commented Jan 23, 2023

I don't think we should support BETWEEN, EXISTS, IS NULL, IS NOT NULL, IS TRUE, IS FALSE, etc. I'm not sure that these work the same across DBMS.

IS NULL, IS NOT NULL are supported already.

If we will support BETWEEN, EXISTS, the difference is only to add = after the key value or not.

@kenjis
Copy link
Member Author

kenjis commented Jan 23, 2023

Another example:

What do you mean?
The following test passes in both before and after this PR:

        $builder = $this->db->table('jobs');

        $where = "IF(RAND()>=0.5,TRUE,FALSE)";
        $builder->where($where, null, false);

        $expectedSQL   = 'SELECT * FROM "jobs" WHERE IF(RAND()>=0.5,TRUE,FALSE)';
        $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));

        $expectedBinds = [];
        $this->assertSame($expectedBinds, $builder->getBinds());

@sclubricants
Copy link
Member

Yes this is correct:

        $where = "IF(RAND()>=0.5,TRUE,FALSE)";
        $builder->where($where, null, false);

I was trying to say we shouldn't support things like:

        $builder->where('column', 'IS NULL');

@kenjis
Copy link
Member Author

kenjis commented Jan 24, 2023

The following is not supported before or after this PR:

$builder->where('column', 'IS NULL');
// 'SELECT * FROM "users" WHERE "column" = 'IS NULL''

The following is also not supported.

$builder->where('column', 'IS NULL', false);
// 'SELECT * FROM "users" WHERE column = IS NULL'

@kenjis
Copy link
Member Author

kenjis commented Jan 27, 2023

@codeigniter4/database-team Can someone review?

Copy link
Member

@michalsn michalsn left a comment

Choose a reason for hiding this comment

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

I'm not a fan of allowing:

$builder->where($where, '', false);

But since developers were using it this way, we shouldn't break their code.

Copy link
Member

@sclubricants sclubricants left a comment

Choose a reason for hiding this comment

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

I'm not sure why we need all of these spelled out.

There are a lot more of these.

SOUNDS LIKE
RLIKE
NOT RLIKE
IS TRUE
IS FALSE
FIND_IN_SET

@kenjis kenjis merged commit 6399bda into codeigniter4:develop Jan 27, 2023
@kenjis kenjis deleted the fix-QB-where-CustomString branch January 27, 2023 23:31
@kenjis
Copy link
Member Author

kenjis commented Jan 27, 2023

Probably no user used these, or did not send a bug report.

In my opinion it is not a good practice to write SQL strings in the key of where().
If a user wants to write SQL strings, it is better to use RawSql.
So I don't think it is necessary to add anything other than what are currently defined.

@kenjis
Copy link
Member Author

kenjis commented Jan 27, 2023

@tangix With this PR, your issue #7117 will be fixed in v4.3.2.
See #7155 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.3 bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants