Skip to content

Commit 2c774ca

Browse files
patel-vanshCopilotneznaika0paulbalandanmichalsn
authored
feat: Add incrementMany() and decrementMany() methods to BaseBuilder and other driver specific builders (#10140)
Co-authored-by: Copilot <copilot@github.com> Co-authored-by: neznaika0 <ozornick.ks@gmail.com> Co-authored-by: John Paul E. Balandan, CPA <paulbalandan@gmail.com> Co-authored-by: Michal Sniatala <michal@sniatala.pl>
1 parent bc3c6b6 commit 2c774ca

9 files changed

Lines changed: 359 additions & 50 deletions

File tree

system/Database/BaseBuilder.php

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use CodeIgniter\Exceptions\InvalidArgumentException;
2020
use CodeIgniter\Traits\ConditionalTrait;
2121
use Config\Feature;
22+
use TypeError;
2223

2324
/**
2425
* Class BaseBuilder
@@ -3021,9 +3022,41 @@ protected function _deleteBatch(string $table, array $keys, array $values): stri
30213022
*/
30223023
public function increment(string $column, int $value = 1)
30233024
{
3024-
$column = $this->db->protectIdentifiers($column);
3025+
return $this->incrementMany([$column], $value);
3026+
}
3027+
3028+
/**
3029+
* Increments multiple numeric columns by the specified value(s).
3030+
*
3031+
* @param array<string, int>|list<string> $columns A list of columns or array of column => value pairs to increment.
3032+
* @param int $value The value to increment by if $columns is a list of column names.
3033+
*/
3034+
public function incrementMany(array $columns, int $value = 1): bool
3035+
{
3036+
if ($columns === []) {
3037+
throw new InvalidArgumentException('Argument #1 ($columns) cannot be empty.');
3038+
}
3039+
3040+
if (array_is_list($columns)) {
3041+
$columns = array_fill_keys($columns, $value);
3042+
}
3043+
3044+
$fields = [];
3045+
3046+
foreach ($columns as $col => $val) {
3047+
if (! is_int($val)) {
3048+
throw new TypeError(sprintf(
3049+
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
3050+
get_debug_type($val),
3051+
$col,
3052+
));
3053+
}
3054+
3055+
$col = $this->db->protectIdentifiers($col);
3056+
$fields[$col] = "{$col} + {$val}";
3057+
}
30253058

3026-
$sql = $this->_update($this->QBFrom[0], [$column => "{$column} + {$value}"]);
3059+
$sql = $this->_update($this->QBFrom[0], $fields);
30273060

30283061
if (! $this->testMode) {
30293062
$this->resetWrite();
@@ -3041,9 +3074,41 @@ public function increment(string $column, int $value = 1)
30413074
*/
30423075
public function decrement(string $column, int $value = 1)
30433076
{
3044-
$column = $this->db->protectIdentifiers($column);
3077+
return $this->decrementMany([$column], $value);
3078+
}
3079+
3080+
/**
3081+
* Decrements multiple numeric columns by the specified value(s).
3082+
*
3083+
* @param array<string, int>|list<string> $columns A list of columns or array of column => value pairs to decrement.
3084+
* @param int $value The value to decrement by if $columns is a list of column names.
3085+
*/
3086+
public function decrementMany(array $columns, int $value = 1): bool
3087+
{
3088+
if ($columns === []) {
3089+
throw new InvalidArgumentException('Argument #1 ($columns) cannot be empty.');
3090+
}
3091+
3092+
if (array_is_list($columns)) {
3093+
$columns = array_fill_keys($columns, $value);
3094+
}
3095+
3096+
$fields = [];
3097+
3098+
foreach ($columns as $col => $val) {
3099+
if (! is_int($val)) {
3100+
throw new TypeError(sprintf(
3101+
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
3102+
get_debug_type($val),
3103+
$col,
3104+
));
3105+
}
3106+
3107+
$col = $this->db->protectIdentifiers($col);
3108+
$fields[$col] = "{$col} - {$val}";
3109+
}
30453110

3046-
$sql = $this->_update($this->QBFrom[0], [$column => "{$column}-{$value}"]);
3111+
$sql = $this->_update($this->QBFrom[0], $fields);
30473112

30483113
if (! $this->testMode) {
30493114
$this->resetWrite();

system/Database/Postgre/Builder.php

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
1818
use CodeIgniter\Database\RawSql;
1919
use CodeIgniter\Exceptions\InvalidArgumentException;
20+
use TypeError;
2021

2122
/**
2223
* Builder for Postgre
@@ -87,17 +88,37 @@ public function orderBy(string $orderBy, string $direction = '', ?bool $escape =
8788
}
8889

8990
/**
90-
* Increments a numeric column by the specified value.
91+
* Increments multiple numeric columns by the specified value(s).
9192
*
92-
* @return mixed
93-
*
94-
* @throws DatabaseException
93+
* @param array<string, int>|list<string> $columns A list of columns or array of column => value pairs to increment.
94+
* @param int $value The value to increment by if $columns is a list of column names.
9595
*/
96-
public function increment(string $column, int $value = 1)
96+
public function incrementMany(array $columns, int $value = 1): bool
9797
{
98-
$column = $this->db->protectIdentifiers($column);
98+
if ($columns === []) {
99+
throw new InvalidArgumentException('Argument #1 ($columns) cannot be empty.');
100+
}
101+
102+
if (array_is_list($columns)) {
103+
$columns = array_fill_keys($columns, $value);
104+
}
105+
106+
$fields = [];
107+
108+
foreach ($columns as $col => $val) {
109+
if (! is_int($val)) {
110+
throw new TypeError(sprintf(
111+
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
112+
get_debug_type($val),
113+
$col,
114+
));
115+
}
116+
117+
$col = $this->db->protectIdentifiers($col);
118+
$fields[$col] = "CAST({$col} AS numeric) + {$val}";
119+
}
99120

100-
$sql = $this->_update($this->QBFrom[0], [$column => "to_number({$column}, '9999999') + {$value}"]);
121+
$sql = $this->_update($this->QBFrom[0], $fields);
101122

102123
if (! $this->testMode) {
103124
$this->resetWrite();
@@ -109,17 +130,37 @@ public function increment(string $column, int $value = 1)
109130
}
110131

111132
/**
112-
* Decrements a numeric column by the specified value.
133+
* Decrements multiple numeric columns by the specified value(s).
113134
*
114-
* @return mixed
115-
*
116-
* @throws DatabaseException
135+
* @param array<string, int>|list<string> $columns A list of columns or array of column => value pairs to decrement.
136+
* @param int $value The value to decrement by if $columns is a list of column names.
117137
*/
118-
public function decrement(string $column, int $value = 1)
138+
public function decrementMany(array $columns, int $value = 1): bool
119139
{
120-
$column = $this->db->protectIdentifiers($column);
140+
if ($columns === []) {
141+
throw new InvalidArgumentException('Argument #1 ($columns) cannot be empty.');
142+
}
143+
144+
if (array_is_list($columns)) {
145+
$columns = array_fill_keys($columns, $value);
146+
}
147+
148+
$fields = [];
149+
150+
foreach ($columns as $col => $val) {
151+
if (! is_int($val)) {
152+
throw new TypeError(sprintf(
153+
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
154+
get_debug_type($val),
155+
$col,
156+
));
157+
}
158+
159+
$col = $this->db->protectIdentifiers($col);
160+
$fields[$col] = "CAST({$col} AS numeric) - {$val}";
161+
}
121162

122-
$sql = $this->_update($this->QBFrom[0], [$column => "to_number({$column}, '9999999') - {$value}"]);
163+
$sql = $this->_update($this->QBFrom[0], $fields);
123164

124165
if (! $this->testMode) {
125166
$this->resetWrite();

system/Database/SQLSRV/Builder.php

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
use CodeIgniter\Database\Exceptions\DataException;
1919
use CodeIgniter\Database\RawSql;
2020
use CodeIgniter\Database\ResultInterface;
21+
use CodeIgniter\Exceptions\InvalidArgumentException;
2122
use Config\Feature;
23+
use TypeError;
2224

2325
/**
2426
* Builder for SQLSRV
@@ -232,21 +234,41 @@ protected function _update(string $table, array $values): string
232234
}
233235

234236
/**
235-
* Increments a numeric column by the specified value.
237+
* Increments multiple numeric columns by the specified value(s).
236238
*
237-
* @return bool
239+
* @param array<string, int>|list<string> $columns A list of columns or array of column => value pairs to increment.
240+
* @param int $value The value to increment by if $columns is a list of column names.
238241
*/
239-
public function increment(string $column, int $value = 1)
242+
public function incrementMany(array $columns, int $value = 1): bool
240243
{
241-
$column = $this->db->protectIdentifiers($column);
244+
if ($columns === []) {
245+
throw new InvalidArgumentException('Argument #1 ($columns) cannot be empty.');
246+
}
242247

243-
if ($this->castTextToInt) {
244-
$values = [$column => "CONVERT(VARCHAR(MAX),CONVERT(INT,CONVERT(VARCHAR(MAX), {$column})) + {$value})"];
245-
} else {
246-
$values = [$column => "{$column} + {$value}"];
248+
if (array_is_list($columns)) {
249+
$columns = array_fill_keys($columns, $value);
250+
}
251+
252+
$fields = [];
253+
254+
foreach ($columns as $col => $val) {
255+
if (! is_int($val)) {
256+
throw new TypeError(sprintf(
257+
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
258+
get_debug_type($val),
259+
$col,
260+
));
261+
}
262+
263+
$col = $this->db->protectIdentifiers($col);
264+
if ($this->castTextToInt) {
265+
$fields[$col] = "CONVERT(VARCHAR(MAX),CONVERT(INT,CONVERT(VARCHAR(MAX), {$col})) + {$val})";
266+
} else {
267+
$fields[$col] = "{$col} + {$val}";
268+
}
247269
}
248270

249-
$sql = $this->_update($this->QBFrom[0], $values);
271+
$sql = $this->_update($this->QBFrom[0], $fields);
250272

251273
if (! $this->testMode) {
252274
$this->resetWrite();
@@ -258,21 +280,41 @@ public function increment(string $column, int $value = 1)
258280
}
259281

260282
/**
261-
* Decrements a numeric column by the specified value.
283+
* Decrements multiple numeric columns by the specified value(s).
262284
*
263-
* @return bool
285+
* @param array<string, int>|list<string> $columns A list of columns or array of column => value pairs to decrement.
286+
* @param int $value The value to decrement by if $columns is a list of column names.
264287
*/
265-
public function decrement(string $column, int $value = 1)
288+
public function decrementMany(array $columns, int $value = 1): bool
266289
{
267-
$column = $this->db->protectIdentifiers($column);
290+
if ($columns === []) {
291+
throw new InvalidArgumentException('Argument #1 ($columns) cannot be empty.');
292+
}
268293

269-
if ($this->castTextToInt) {
270-
$values = [$column => "CONVERT(VARCHAR(MAX),CONVERT(INT,CONVERT(VARCHAR(MAX), {$column})) - {$value})"];
271-
} else {
272-
$values = [$column => "{$column} + {$value}"];
294+
if (array_is_list($columns)) {
295+
$columns = array_fill_keys($columns, $value);
296+
}
297+
298+
$fields = [];
299+
300+
foreach ($columns as $col => $val) {
301+
if (! is_int($val)) {
302+
throw new TypeError(sprintf(
303+
'Argument #1 ($columns) must contain only int values, %s given for "%s".',
304+
get_debug_type($val),
305+
$col,
306+
));
307+
}
308+
309+
$col = $this->db->protectIdentifiers($col);
310+
if ($this->castTextToInt) {
311+
$fields[$col] = "CONVERT(VARCHAR(MAX),CONVERT(INT,CONVERT(VARCHAR(MAX), {$col})) - {$val})";
312+
} else {
313+
$fields[$col] = "{$col} - {$val}";
314+
}
273315
}
274316

275-
$sql = $this->_update($this->QBFrom[0], $values);
317+
$sql = $this->_update($this->QBFrom[0], $fields);
276318

277319
if (! $this->testMode) {
278320
$this->resetWrite();

0 commit comments

Comments
 (0)