Skip to content

Commit

Permalink
InsertBatch and UpdateBatch now included in Model and will validate e…
Browse files Browse the repository at this point in the history
…ach row prior to saving. Fixes #967
  • Loading branch information
lonnieezell committed Jul 18, 2018
1 parent 67aadd9 commit f5e1541
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 12 deletions.
22 changes: 11 additions & 11 deletions system/Database/BaseBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1508,13 +1508,13 @@ public function getWhere($where = null, $limit = null, $offset = null)
* @param array $set An associative array of insert values
* @param bool $escape Whether to escape values and identifiers
*
* @param int $batch_size
* @param int $batchSize
* @param bool $testing
*
* @return int Number of rows inserted or FALSE on failure
* @throws DatabaseException
*/
public function insertBatch($set = null, $escape = null, $batch_size = 100, $testing = false)
public function insertBatch($set = null, $escape = null, $batchSize = 100, $testing = false)
{
if ($set === null)
{
Expand Down Expand Up @@ -1547,9 +1547,9 @@ public function insertBatch($set = null, $escape = null, $batch_size = 100, $tes

// Batch this baby
$affected_rows = 0;
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batch_size)
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batchSize)
{
$sql = $this->_insertBatch($this->db->protectIdentifiers($table, true, $escape, false), $this->QBKeys, array_slice($this->QBSet, $i, $batch_size));
$sql = $this->_insertBatch($this->db->protectIdentifiers($table, true, $escape, false), $this->QBKeys, array_slice($this->QBSet, $i, $batchSize));

if ($testing)
{
Expand Down Expand Up @@ -1975,15 +1975,15 @@ protected function validateUpdate()
*
* Compiles an update string and runs the query
*
* @param array $set An associative array of update values
* @param string $index The where key
* @param int $batch_size The size of the batch to run
* @param bool $returnSQL True means SQL is returned, false will execute the query
* @param array $set An associative array of update values
* @param string $index The where key
* @param int $batchSize The size of the batch to run
* @param bool $returnSQL True means SQL is returned, false will execute the query
*
* @return mixed Number of rows affected or FALSE on failure
* @throws \CodeIgniter\Database\Exceptions\DatabaseException
*/
public function updateBatch($set = null, $index = null, $batch_size = 100, $returnSQL = false)
public function updateBatch($set = null, $index = null, $batchSize = 100, $returnSQL = false)
{
if ($index === null)
{
Expand Down Expand Up @@ -2025,9 +2025,9 @@ public function updateBatch($set = null, $index = null, $batch_size = 100, $retu
// Batch this baby
$affected_rows = 0;
$savedSQL = [];
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batch_size)
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batchSize)
{
$sql = $this->_updateBatch($table, array_slice($this->QBSet, $i, $batch_size), $this->db->protectIdentifiers($index)
$sql = $this->_updateBatch($table, array_slice($this->QBSet, $i, $batchSize), $this->db->protectIdentifiers($index)
);

if ($returnSQL)
Expand Down
4 changes: 3 additions & 1 deletion system/HTTP/Exceptions/HTTPException.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,11 @@ public static function forAlreadyMoved()
/**
* For Uploaded file move
*
* @param string|null $path
*
* @return \CodeIgniter\HTTP\Exceptions\HTTPException
*/
public static function forInvalidFile()
public static function forInvalidFile(string $path=null)
{
return new static(lang('HTTP.invalidFile'));
}
Expand Down
60 changes: 60 additions & 0 deletions system/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,35 @@ public function insert($data = null, bool $returnID = true)

//--------------------------------------------------------------------

/**
* Compiles batch insert strings and runs the queries, validating each row prior.
*
* @param array $set An associative array of insert values
* @param bool $escape Whether to escape values and identifiers
*
* @param int $batchSize
* @param bool $testing
*
* @return int Number of rows inserted or FALSE on failure
*/
public function insertBatch($set = null, $escape = null, $batchSize = 100, $testing = false)
{
if (is_array($set) && $this->skipValidation === false)
{
foreach ($set as $row)
{
if ($this->validate($row) === false)
{
return false;
}
}
}

return $this->builder()->insertBatch($set, $escape, $batchSize, $testing);
}

//--------------------------------------------------------------------

/**
* Updates a single record in $this->table. If an object is provided,
* it will attempt to convert it into an array.
Expand Down Expand Up @@ -712,6 +741,37 @@ public function update($id = null, $data = null)

//--------------------------------------------------------------------

/**
* Update_Batch
*
* Compiles an update string and runs the query
*
* @param array $set An associative array of update values
* @param string $index The where key
* @param int $batchSize The size of the batch to run
* @param bool $returnSQL True means SQL is returned, false will execute the query
*
* @return mixed Number of rows affected or FALSE on failure
* @throws \CodeIgniter\Database\Exceptions\DatabaseException
*/
public function updateBatch($set = null, $index = null, $batchSize = 100, $returnSQL = false)
{
if (is_array($set) && $this->skipValidation === false)
{
foreach ($set as $row)
{
if ($this->validate($row) === false)
{
return false;
}
}
}

return $this->builder()->updateBatch($set, $index, $batchSize, $returnSQL);
}

//--------------------------------------------------------------------

/**
* Deletes a single record from $this->table where $id matches
* the table's primaryKey
Expand Down
79 changes: 79 additions & 0 deletions tests/system/Database/Live/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -633,4 +633,83 @@ public function testUpdateArray()
$this->seeInDatabase('user', ['id' => 1, 'name' => 'Foo Bar']);
$this->seeInDatabase('user', ['id' => 2, 'name' => 'Foo Bar']);
}

public function testInsertBatchSuccess()
{
$job_data = [
['name' => 'Comedian', 'description' => 'Theres something in your teeth'],
['name' => 'Cab Driver', 'description' => 'Iam yellow'],
];

$model = new JobModel($this->db);
$model->insertBatch($job_data);

$this->seeInDatabase('job', ['name' => 'Comedian']);
$this->seeInDatabase('job', ['name' => 'Cab Driver']);
}

public function testInsertBatchValidationFail()
{
$job_data = [
['name' => 'Comedian', 'description' => null],
];

$model = new JobModel($this->db);

$this->setPrivateProperty($model, 'validationRules', ['description' => 'required']);

$this->assertFalse($model->insertBatch($job_data));

$error = $model->errors();
$this->assertTrue(isset($error['description']));
}

public function testUpdateBatchSuccess()
{
$data = [
[
'name' => 'Derek Jones',
'country' => 'Greece'
],
[
'name' => 'Ahmadinejad',
'country' => 'Greece'
],
];

$model = new EventModel($this->db);

$model->updateBatch($data, 'name');

$this->seeInDatabase('user', [
'name' => 'Derek Jones',
'country' => 'Greece'
]);
$this->seeInDatabase('user', [
'name' => 'Ahmadinejad',
'country' => 'Greece'
]);
}

//--------------------------------------------------------------------

public function testUpdateBatchValidationFail()
{
$data = [
[
'name' => 'Derek Jones',
'country' => null
],
];

$model = new EventModel($this->db);
$this->setPrivateProperty($model, 'validationRules', ['country' => 'required']);

$this->assertFalse($model->updateBatch($data, 'name'));

$error = $model->errors();
$this->assertTrue(isset($error['country']));
}

//--------------------------------------------------------------------
}

0 comments on commit f5e1541

Please sign in to comment.