123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- <?php
- namespace Drupal\KernelTests\Core\Database;
- use Drupal\Core\Database\Database;
- use Drupal\Core\Database\IntegrityConstraintViolationException;
- /**
- * Tests handling of some invalid data.
- *
- * @group Database
- */
- class InvalidDataTest extends DatabaseTestBase {
- /**
- * Tests aborting of traditional SQL database systems with invalid data.
- */
- public function testInsertDuplicateData() {
- // Try to insert multiple records where at least one has bad data.
- try {
- $this->connection->insert('test')
- ->fields(['name', 'age', 'job'])
- ->values([
- 'name' => 'Elvis',
- 'age' => 63,
- 'job' => 'Singer',
- ])->values([
- // Duplicate value on unique field.
- 'name' => 'John',
- 'age' => 17,
- 'job' => 'Consultant',
- ])
- ->values([
- 'name' => 'Frank',
- 'age' => 75,
- 'job' => 'Singer',
- ])
- ->execute();
- $this->fail('Insert succeeded when it should not have.');
- }
- catch (IntegrityConstraintViolationException $e) {
- // Check if the first record was inserted.
- $name = $this->connection->query('SELECT name FROM {test} WHERE age = :age', [':age' => 63])->fetchField();
- if ($name == 'Elvis') {
- 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 other values were not inserted.
- $record = $this->connection->select('test')
- ->fields('test', ['name', 'age'])
- ->condition('age', [17, 75], 'IN')
- ->execute()->fetchObject();
- $this->assertFalse($record, 'The rest of the insert aborted as expected.');
- }
- }
- /**
- * 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.
- $this->connection->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 = $this->connection->select('test_people', 'tp')
- ->fields('tp', ['name', 'age', 'job'])
- ->orderBy('name');
- // Try inserting from the subselect.
- $this->connection->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 = $this->connection->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 = $this->connection->select('test')
- ->fields('test', ['name', 'age'])
- ->condition('age', [17, 30], 'IN')
- ->execute()->fetchObject();
- $this->assertFalse($record, 'The rest of the insert aborted as expected.');
- }
- }
- }
|