Skip to content

Commit 7e2a0a7

Browse files
committed
Fix _insertBatch()
Made some format changes and added caching to the insert queries. Also added function getValues() which compiles data in sets of ().
1 parent 2b7e85d commit 7e2a0a7

File tree

6 files changed

+84
-25
lines changed

6 files changed

+84
-25
lines changed

system/Database/BaseBuilder.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,7 +1950,7 @@ protected function getValues(array $values): array
19501950
public function insertBatch($set = null, ?bool $escape = null, int $batchSize = 100)
19511951
{
19521952
if ($set !== null) {
1953-
$this->setBatch($set, $escape);
1953+
$this->setData($set, $escape);
19541954
}
19551955

19561956
return $this->batchExecute('_insertBatch', $batchSize);
@@ -1961,7 +1961,23 @@ public function insertBatch($set = null, ?bool $escape = null, int $batchSize =
19611961
*/
19621962
protected function _insertBatch(string $table, array $keys, array $values): string
19631963
{
1964-
return 'INSERT ' . $this->compileIgnore('insert') . 'INTO ' . $table . ' (' . implode(', ', $keys) . ') VALUES ' . implode(', ', $values);
1964+
$sql = $this->QBOptions['sql'] ?? '';
1965+
1966+
// if this is the first iteration of batch then we need to build skeleton sql
1967+
if ($sql === '') {
1968+
$sql = 'INSERT ' . $this->compileIgnore('insert') . 'INTO ' . $table
1969+
. ' (' . implode(', ', $keys) . ")\n%s";
1970+
1971+
$this->QBOptions['sql'] = $sql;
1972+
}
1973+
1974+
if (isset($this->QBOptions['fromQuery'])) {
1975+
$data = $this->QBOptions['fromQuery'];
1976+
} else {
1977+
$data = 'VALUES ' . implode(', ', $this->getValues($values));
1978+
}
1979+
1980+
return sprintf($sql, $data);
19651981
}
19661982

19671983
/**
@@ -2361,7 +2377,7 @@ protected function _updateBatch(string $table, array $keys, array $values): stri
23612377
' AND ',
23622378
array_map(
23632379
static fn ($key) => ($key instanceof RawSql ?
2364-
str_replace('%', '%%', $key) :
2380+
str_replace('%', '%%', (string) $key) :
23652381
$table . '.' . $key . ' = ' . $alias . '.' . $key),
23662382
$constraints
23672383
)
@@ -2821,7 +2837,7 @@ protected function unionInjection(string $sql): string
28212837
/**
28222838
* Takes an object as input and converts the class variables to array key/vals
28232839
*
2824-
* @param object $object
2840+
* @param array|object $object
28252841
*
28262842
* @return array
28272843
*/
@@ -2845,7 +2861,7 @@ protected function objectToArray($object)
28452861
/**
28462862
* Takes an object as input and converts the class variables to array key/vals
28472863
*
2848-
* @param object $object
2864+
* @param array|object $object
28492865
*
28502866
* @return array
28512867
*/

system/Database/MySQLi/Builder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ protected function _updateBatch(string $table, array $keys, array $values): stri
9191
' AND ',
9292
array_map(
9393
static fn ($key) => ($key instanceof RawSql ?
94-
str_replace('%', '%%', $key) :
94+
str_replace('%', '%%', (string) $key) :
9595
$table . '.' . $key . ' = ' . $alias . '.' . $key),
9696
$constraints
9797
)

system/Database/OCI8/Builder.php

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,36 @@ class Builder extends BaseBuilder
6868
*/
6969
protected function _insertBatch(string $table, array $keys, array $values): string
7070
{
71-
$insertKeys = implode(', ', $keys);
72-
$hasPrimaryKey = in_array('PRIMARY', array_column($this->db->getIndexData($table), 'type'), true);
71+
$sql = $this->QBOptions['sql'] ?? '';
7372

74-
// ORA-00001 measures
75-
if ($hasPrimaryKey) {
76-
$sql = 'INSERT INTO ' . $table . ' (' . $insertKeys . ") \n SELECT * FROM (\n";
77-
$selectQueryValues = [];
73+
// if this is the first iteration of batch then we need to build skeleton sql
74+
if ($sql === '') {
75+
$insertKeys = implode(', ', $keys);
76+
$hasPrimaryKey = in_array('PRIMARY', array_column($this->db->getIndexData($table), 'type'), true);
7877

79-
foreach ($values as $value) {
80-
$selectValues = implode(',', array_map(static fn ($value, $key) => $value . ' as ' . $key, explode(',', substr(substr($value, 1), 0, -1)), $keys));
81-
$selectQueryValues[] = 'SELECT ' . $selectValues . ' FROM DUAL';
82-
}
78+
// ORA-00001 measures
79+
$sql = 'INSERT' . ($hasPrimaryKey ? '' : ' ALL') . ' INTO ' . $table . ' (' . $insertKeys . ")\n%s";
8380

84-
return $sql . implode("\n UNION ALL \n", $selectQueryValues) . "\n)";
81+
$this->QBOptions['sql'] = $sql;
8582
}
8683

87-
$sql = "INSERT ALL\n";
88-
89-
foreach ($values as $value) {
90-
$sql .= ' INTO ' . $table . ' (' . $insertKeys . ') VALUES ' . $value . "\n";
84+
if (isset($this->QBOptions['fromQuery'])) {
85+
$data = $this->QBOptions['fromQuery'];
86+
} else {
87+
$data = implode(
88+
" FROM DUAL UNION ALL\n",
89+
array_map(
90+
static fn ($value) => 'SELECT ' . implode(', ', array_map(
91+
static fn ($key, $index) => $index . ' ' . $key,
92+
$keys,
93+
$value
94+
)),
95+
$values
96+
)
97+
) . " FROM DUAL\n";
9198
}
9299

93-
return $sql . 'SELECT * FROM DUAL';
100+
return sprintf($sql, $data);
94101
}
95102

96103
/**
@@ -265,7 +272,7 @@ protected function _updateBatch(string $table, array $keys, array $values): stri
265272
' AND ',
266273
array_map(
267274
static fn ($key) => ($key instanceof RawSql ?
268-
str_replace('%', '%%', $key) :
275+
str_replace('%', '%%', (string) $key) :
269276
$table . '.' . $key . ' = ' . $alias . '.' . $key),
270277
$constraints
271278
)

system/Database/Postgre/Builder.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,24 @@ protected function _insert(string $table, array $keys, array $unescapedKeys): st
196196
*/
197197
protected function _insertBatch(string $table, array $keys, array $values): string
198198
{
199-
return trim(sprintf('INSERT INTO %s (%s) VALUES %s %s', $table, implode(', ', $keys), implode(', ', $values), $this->compileIgnore('insert')));
199+
$sql = $this->QBOptions['sql'] ?? '';
200+
201+
// if this is the first iteration of batch then we need to build skeleton sql
202+
if ($sql === '') {
203+
$sql = 'INSERT INTO ' . $table . '(' . implode(', ', $keys) . ")\n%s\n";
204+
205+
$sql .= $this->compileIgnore('insert');
206+
207+
$this->QBOptions['sql'] = $sql;
208+
}
209+
210+
if (isset($this->QBOptions['fromQuery'])) {
211+
$data = $this->QBOptions['fromQuery'];
212+
} else {
213+
$data = 'VALUES ' . implode(', ', $this->getValues($values));
214+
}
215+
216+
return sprintf($sql, $data);
200217
}
201218

202219
/**

system/Database/SQLSRV/Builder.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,23 @@ protected function _insert(string $table, array $keys, array $unescapedKeys): st
180180
*/
181181
protected function _insertBatch(string $table, array $keys, array $values): string
182182
{
183-
return 'INSERT ' . $this->compileIgnore('insert') . 'INTO ' . $this->getFullName($table) . ' (' . implode(', ', $keys) . ') VALUES ' . implode(', ', $values);
183+
$sql = $this->QBOptions['sql'] ?? '';
184+
185+
// if this is the first iteration of batch then we need to build skeleton sql
186+
if ($sql === '') {
187+
$sql = 'INSERT ' . $this->compileIgnore('insert') . 'INTO ' . $this->getFullName($table)
188+
. ' (' . implode(', ', $keys) . ")\n%s";
189+
190+
$this->QBOptions['sql'] = $sql;
191+
}
192+
193+
if (isset($this->QBOptions['fromQuery'])) {
194+
$data = $this->QBOptions['fromQuery'];
195+
} else {
196+
$data = 'VALUES ' . implode(', ', $this->getValues($values));
197+
}
198+
199+
return sprintf($sql, $data);
184200
}
185201

186202
/**

system/Database/SQLite3/Builder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace CodeIgniter\Database\SQLite3;
1313

1414
use CodeIgniter\Database\BaseBuilder;
15+
use CodeIgniter\Database\Exceptions\DatabaseException;
1516

1617
/**
1718
* Builder for SQLite3
@@ -80,6 +81,8 @@ protected function _updateBatch(string $table, array $keys, array $values): stri
8081
return parent::_updateBatch($table, $keys, $values);
8182
}
8283

84+
$constraints = $this->QBOptions['constraints'] ?? [];
85+
8386
if (count($constraints) > 1 || isset($this->QBOptions['fromQuery'])) {
8487
throw new DatabaseException('You are trying to use a feature which requires SQLite version 3.33 or higher.');
8588
}

0 commit comments

Comments
 (0)