feat: Add incrementAll() and decrementAll() methods to BaseBuilder and other driver specific builders#10140
feat: Add incrementAll() and decrementAll() methods to BaseBuilder and other driver specific builders#10140patel-vansh wants to merge 7 commits intocodeigniter4:4.8from
incrementAll() and decrementAll() methods to BaseBuilder and other driver specific builders#10140Conversation
…ns as input Co-authored-by: Copilot <copilot@github.com>
paulbalandan
left a comment
There was a problem hiding this comment.
Have you considered adding a separate incrementAll (or other wording) that will take care of the array, so to minimize the BC break?
PS. The random test failure seems legitimate. I'll deal with that later.
|
I also think that |
|
Yeah, that would avoid BC. I guess Maybe the current increment method calls incrementAll internally? So, there's no duplication of any logic. |
I see why not. |
Co-authored-by: Copilot <copilot@github.com>
incrementAll() and decrementAll() methods to BaseBuilder and other driver specific builders
|
Not sure why PHPStan analysis have failed. |
|
You apparently fixed (or renamed) the affected code. Just run |
michalsn
left a comment
There was a problem hiding this comment.
Supporting a more convenient API would be nice:
incrementAll(['one', 'two'], 2)
incrementAll(['one' => 2, 'two' => 3])What do you think?
Something like:
public function incrementAll(array $columns, int $value = 1): bool
{
$fields = [];
if (array_is_list($columns)) {
foreach ($columns as $column) {
$column = $this->db->protectIdentifiers($column);
$fields[$column] = "{$column} + {$value}";
}
} else {
foreach ($columns as $column => $value) {
if (! is_int($value)) {
throw new TypeError(...);
}
$column = $this->db->protectIdentifiers($column);
$fields[$column] = "{$column} + {$value}";
}
}
// ...
}| foreach ($columns as $col => $val) { | ||
| $col = $this->db->protectIdentifiers($col); | ||
| $fields[$col] = "{$col} + {$val}"; | ||
| } |
There was a problem hiding this comment.
Since we no longer have runtime type enforcement for each value, we should add a check manually. Something like:
if (! is_int($val)) {
throw new TypeError(sprintf(
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
get_debug_type($val),
(string) $col,
));
}| if ($this->castTextToInt) { | ||
| $values = [$column => "CONVERT(VARCHAR(MAX),CONVERT(INT,CONVERT(VARCHAR(MAX), {$column})) - {$value})"]; | ||
| } else { | ||
| $values = [$column => "{$column} + {$value}"]; |
There was a problem hiding this comment.
Hmm. Comparing this removed L272 against the new L277. It seems an unnoticed bug in decrement if $this->castTextToInt is false. I think this deserves a separate bug fix in develop.
| } | ||
|
|
||
| $sql = $this->_update($this->QBFrom[0], [$column => "{$column} + {$value}"]); | ||
| $sql = $this->_update($this->QBFrom[0], $fields); |
There was a problem hiding this comment.
What if $columns is [] then $fields is also []. Would that cause issues in the SQL? We should do something with that, either throwing or early return. Either way, we need tests to lock in.
| $this->seeInDatabase('job', ['name' => 'incremental', 'description' => '8']); | ||
| } | ||
|
|
||
| public function testIncrementAll(): void |
There was a problem hiding this comment.
Can you move this test after all increment tests, then replicate the 3 testing done ( base increment test, with value, and reset state). Same goes for decrement.
|
|
||
| $this->db->table('task') | ||
| ->where('name', 'task1') | ||
| ->incrementAll(['description' => 2, 'priority' => 3]); |
There was a problem hiding this comment.
Does this accept negative values? If yes, maybe add some to the tests?
|
|
||
| :param string $column: The name of the column to increment | ||
| :param int $value: The amount to increment in the column | ||
| :param int $value: The amount to increment in the column |
There was a problem hiding this comment.
Do you mean to align this with above param?
| * @param array<string, int> $columns An array of column => value pairs to increment. | ||
| */ | ||
| public function increment(string $column, int $value = 1) | ||
| public function incrementAll(array $columns): bool |
There was a problem hiding this comment.
I'm rethinking now my suggestion for incrementAll naming. Would it create ambiguity to anyone reading it by function name only on what it is incrementing?
Description
This PR adds two new functions in
BaseBuilder.php—incrementAll()anddecrementAll(). These two functions enable devs to increment/decrement multiple rows at once atomically.Also, the
increment()anddecrement()methods now internally callincrementAll()anddecrementAll()respectively to prevent duplicating the logic.Checklist: