Skip to content

fix: simulate query matched rows wrong count#18536

Merged
MauricioFauth merged 6 commits intophpmyadmin:QA_5_2from
kamioon:QA_5_2
Aug 26, 2023
Merged

fix: simulate query matched rows wrong count#18536
MauricioFauth merged 6 commits intophpmyadmin:QA_5_2from
kamioon:QA_5_2

Conversation

@kamioon
Copy link
Contributor

@kamioon kamioon commented Jul 16, 2023

This is a bug fix for #18533
The <> operator excludes NULL values. read more

Fixes: #18533

Signed-off-by: kamioon <kamran.azari@gmail.com>
@codecov
Copy link

codecov bot commented Jul 16, 2023

Codecov Report

Patch coverage has no change and project coverage change: -0.27 ⚠️

Comparison is base (aa3496f) 48.02% compared to head (824f850) 47.76%.

❗ Current head 824f850 differs from pull request most recent head 1551484. Consider uploading reports for the commit 1551484 to get more accurate results

Additional details and impacted files
@@             Coverage Diff              @@
##             QA_5_2   #18536      +/-   ##
============================================
- Coverage     48.02%   47.76%   -0.27%     
+ Complexity    17011    17010       -1     
============================================
  Files           607      607              
  Lines         72342    72339       -3     
============================================
- Hits          34741    34550     -191     
- Misses        37601    37789     +188     
Flag Coverage Δ
dbase-extension 48.58% <0.00%> (-0.02%) ⬇️
recode-extension 48.06% <0.00%> (-0.03%) ⬇️
unit-7.2-ubuntu-latest 48.06% <0.00%> (+<0.01%) ⬆️
unit-7.3-ubuntu-latest 48.51% <0.00%> (+0.02%) ⬆️
unit-7.4-ubuntu-latest 48.46% <0.00%> (-0.04%) ⬇️
unit-8.0-ubuntu-latest 48.50% <0.00%> (-0.03%) ⬇️
unit-8.1-ubuntu-latest 48.49% <0.00%> (-0.81%) ⬇️
unit-8.2-ubuntu-latest 48.53% <0.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
libraries/classes/Import/SimulateDml.php 53.33% <0.00%> (-30.80%) ⬇️

... and 5 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

$notEqualOperator = ' IS NOT ';
$diff[] = $set->column . ' IS NOT ' . $set->value;
}else{
$diff[] = '(' . $set->column . ' <> ' . $set->value . ' OR ' . $set->column . ' IS NULL)';
Copy link
Contributor

Choose a reason for hiding this comment

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

I would get rid of both parentheses here, since aren't need. Examples of generated queries with and without parentheses.

SELECT `b` FROM `test` WHERE `a` = 2 AND ((`b` <> 'test' OR `b` IS NULL))
SELECT `b` FROM `test` WHERE `a` = 2 AND (`b` <> 'test' OR `b` IS NULL)

SELECT `b`, `c` FROM `test` WHERE `a` = 1 AND ((`b` <> 'test' OR `b` IS NULL) OR (`c` <> 'test' OR `c` IS NULL))
SELECT `b`, `c` FROM `test` WHERE `a` = 1 AND (`b` <> 'test' OR `b` IS NULL OR `c` <> 'test' OR `c` IS NULL)

SELECT `b`, `c` FROM `test` WHERE `a` = 2 AND (`b` IS NOT NULL OR (`c` <> 'test' OR `c` IS NULL))
SELECT `b`, `c` FROM `test` WHERE `a` = 2 AND (`b` IS NOT NULL OR `c` <> 'test' OR `c` IS NULL)

Copy link
Contributor Author

@kamioon kamioon Jul 17, 2023

Choose a reason for hiding this comment

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

It makes sense. considering that they are all OR, it is not really necessary. I've removed them.

add space before and after the else keyword

Signed-off-by: kamioon <kamran.azari@gmail.com>
Comment on lines 135 to 139
if (strtoupper($set->value) === 'NULL') {
$notEqualOperator = ' IS NOT ';
$diff[] = $set->column . ' IS NOT ' . $set->value;
} else {
$diff[] = $set->column . ' <> ' . $set->value . ' OR ' . $set->column . ' IS NULL';
}
Copy link
Contributor

@MoonE MoonE Jul 17, 2023

Choose a reason for hiding this comment

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

Some love for the MySQL <=> operator?

Suggested change
if (strtoupper($set->value) === 'NULL') {
$notEqualOperator = ' IS NOT ';
$diff[] = $set->column . ' IS NOT ' . $set->value;
} else {
$diff[] = $set->column . ' <> ' . $set->value . ' OR ' . $set->column . ' IS NULL';
}
$diff[] = 'NOT ' . $set->column . ' <=> (' . $set->value . ')';

Copy link
Member

Choose a reason for hiding this comment

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

It broke my brain 😂
Thanks for sharing it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you @MoonE ! I kept the additional parentheses that you have added it seems to keep the value safe. but are there any special conditions without them that ruin the query?

Copy link
Contributor

Choose a reason for hiding this comment

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

This can happen with an update query like

UPDATE a SET b = c OR d WHERE e OR f

It would generate NOT b <=> c OR d instead of NOT b <=> (c OR d)

With that in mind the original condition should also be set in parenthesis:

        if (! empty($diff)) {
-            $where .= ' AND (' . implode(' OR ', $diff) . ')';
+            $where = '(' . $where . ') AND (' . implode(' OR ', $diff) . ')';
        }

to generate the condition
WHERE (e OR f) AND (NOT b <=> (c OR d)) instead of
WHERE e OR f AND (NOT b <=> (c OR d))

Signed-off-by: kamioon <kamran.azari@gmail.com>
Copy link
Member

@williamdes williamdes left a comment

Choose a reason for hiding this comment

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

This looks good

@williamdes williamdes requested a review from MauricioFauth July 18, 2023 07:14
@MoonE
Copy link
Contributor

MoonE commented Jul 19, 2023

@kamioon You also need to adjust the test here

'update statement' => [
'UPDATE `table_1` SET `id` = 20 WHERE `id` > 10',
'SELECT `id` FROM `table_1` WHERE `id` > 10 AND (`id` <> 20)',
],

and also modify the same query here
[
'query' => 'SELECT `id` FROM `table_1` WHERE `id` > 10 AND (`id` <> 20)',
'columns' => ['id'],
'result' => [['11'], ['12']],
],

@williamdes @MauricioFauth Unit tests still pass because the test is marked incomplete here

Assert::markTestIncomplete('Non expected select of database: ' . $databaseName);

and PHPUnit is not run with --fail-on-incomplete / failOnIncomplete="true"

Copy link
Contributor

@MoonE MoonE left a comment

Choose a reason for hiding this comment

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

For what it's woth, I think this is ready.

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