Issue #2871004 by mondrake: Add a test for INSERTing invalid data fetched from a subselect query
parent
d708605724
commit
45e8efc948
|
@ -66,4 +66,81 @@ class InvalidDataTest extends DatabaseTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests inserting with invalid data from a select query.
|
||||
*/
|
||||
public function testInsertDuplicateDataFromSelect() {
|
||||
// Insert multiple records in 'test_people' where one has bad data
|
||||
// (duplicate key). A 'Meredith' record has already been inserted
|
||||
// in ::setUp.
|
||||
db_insert('test_people')
|
||||
->fields(['name', 'age', 'job'])
|
||||
->values([
|
||||
'name' => 'Elvis',
|
||||
'age' => 63,
|
||||
'job' => 'Singer',
|
||||
])->values([
|
||||
// Duplicate value on unique field 'name' for later INSERT in 'test'
|
||||
// table.
|
||||
'name' => 'John',
|
||||
'age' => 17,
|
||||
'job' => 'Consultant',
|
||||
])
|
||||
->values([
|
||||
'name' => 'Frank',
|
||||
'age' => 75,
|
||||
'job' => 'Bass',
|
||||
])
|
||||
->execute();
|
||||
|
||||
try {
|
||||
// Define the subselect query. Add ORDER BY to ensure we have consistent
|
||||
// order in results. Will return:
|
||||
// 0 => [name] => Elvis, [age] => 63, [job] => Singer
|
||||
// 1 => [name] => Frank, [age] => 75, [job] => Bass
|
||||
// 2 => [name] => John, [age] => 17, [job] => Consultant
|
||||
// 3 => [name] => Meredith, [age] => 30, [job] => Speaker
|
||||
// Records 0 and 1 should pass, record 2 should lead to integrity
|
||||
// constraint violation.
|
||||
$query = db_select('test_people', 'tp')
|
||||
->fields('tp', ['name', 'age', 'job'])
|
||||
->orderBy('name');
|
||||
|
||||
// Try inserting from the subselect.
|
||||
db_insert('test')
|
||||
->from($query)
|
||||
->execute();
|
||||
|
||||
$this->fail('Insert succeeded when it should not have.');
|
||||
}
|
||||
catch (IntegrityConstraintViolationException $e) {
|
||||
// Check if the second record was inserted.
|
||||
$name = db_query('SELECT name FROM {test} WHERE age = :age', [':age' => 75])->fetchField();
|
||||
|
||||
if ($name == 'Frank') {
|
||||
if (!Database::getConnection()->supportsTransactions()) {
|
||||
// This is an expected fail.
|
||||
// Database engines that don't support transactions can leave partial
|
||||
// inserts in place when an error occurs. This is the case for MySQL
|
||||
// when running on a MyISAM table.
|
||||
$this->pass("The whole transaction has not been rolled-back when a duplicate key insert occurs, this is expected because the database doesn't support transactions");
|
||||
}
|
||||
else {
|
||||
$this->fail('The whole transaction is rolled back when a duplicate key insert occurs.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->pass('The whole transaction is rolled back when a duplicate key insert occurs.');
|
||||
}
|
||||
|
||||
// Ensure the values for records 2 and 3 were not inserted.
|
||||
$record = db_select('test')
|
||||
->fields('test', ['name', 'age'])
|
||||
->condition('age', [17, 30], 'IN')
|
||||
->execute()->fetchObject();
|
||||
|
||||
$this->assertFalse($record, 'The rest of the insert aborted as expected.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue