Commit bacf782e authored by catch's avatar catch
Browse files

Issue #2999569 by mondrake, Hardik_Patel_12, ravi.shankar, vsujeetkumar,...

Issue #2999569 by mondrake, Hardik_Patel_12, ravi.shankar, vsujeetkumar, mrinalini9, daffie: MySql driver throws a generic DatabaseExceptionWrapper for integrity violation at insertion when column has no default
parent a32afce1
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace Drupal\Core\Database\Driver\mysql;

use Drupal\Core\Database\DatabaseAccessDeniedException;
use Drupal\Core\Database\IntegrityConstraintViolationException;
use Drupal\Core\Database\DatabaseExceptionWrapper;

use Drupal\Core\Database\Database;
@@ -87,6 +88,24 @@ public function query($query, array $args = [], $options = []) {
    }
  }

  /**
   * {@inheritdoc}
   */
  protected function handleQueryException(\PDOException $e, $query, array $args = [], $options = []) {
    // In case of attempted INSERT of a record with an undefined column and no
    // default value indicated in schema, MySql returns a 1364 error code.
    // Throw an IntegrityConstraintViolationException here like the other
    // drivers do, to avoid the parent class to throw a generic
    // DatabaseExceptionWrapper instead.
    if (!empty($e->errorInfo[1]) && $e->errorInfo[1] === 1364) {
      $query_string = ($query instanceof StatementInterface) ? $query->getQueryString() : $query;
      $message = $e->getMessage() . ": " . $query_string . "; " . print_r($args, TRUE);
      throw new IntegrityConstraintViolationException($message, is_int($e->getCode()) ? $e->getCode() : 0, $e);
    }

    parent::handleQueryException($e, $query, $args, $options);
  }

  /**
   * {@inheritdoc}
   */
+24 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

namespace Drupal\KernelTests\Core\Database;

use Drupal\Core\Database\IntegrityConstraintViolationException;

/**
 * Tests the insert builder.
 *
@@ -208,4 +210,26 @@ public function testSpecialColumnInsert() {
    $this->assertEquals('Update value 2', $saved_value);
  }

  /**
   * Tests insertion integrity violation with no default value for a column.
   */
  public function testInsertIntegrityViolation() {
    // Remove the default from the 'age' column, so that inserting a record
    // without its value specified will lead to integrity failure.
    $this->connection->schema()->changeField('test', 'age', 'age', [
      'description' => "The person's age",
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ]);

    // Try inserting a record that misses the value for the 'age' column,
    // should raise an IntegrityConstraintViolationException.
    $this->expectException(IntegrityConstraintViolationException::class);
    $this->connection->insert('test')
      ->fields(['name'])
      ->values(['name' => 'Elvis'])
      ->execute();
  }

}
+7 −14
Original line number Diff line number Diff line
@@ -4,7 +4,6 @@

use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Database\Database;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Database\IntegrityConstraintViolationException;
use Drupal\Core\Entity\ContentEntityType;
use Drupal\Core\Entity\EntityStorageException;
@@ -482,8 +481,7 @@ public function testBundleFieldCreateDeleteWithExistingEntities() {
        ->execute();
      $this->fail($message);
    }
    catch (\RuntimeException $e) {
      if ($e instanceof DatabaseExceptionWrapper || $e instanceof IntegrityConstraintViolationException) {
    catch (IntegrityConstraintViolationException $e) {
      // Now provide a value for the 'not null' column. This is expected to
      // succeed.
      $values['new_bundle_field_shape'] = $this->randomString();
@@ -491,11 +489,6 @@ public function testBundleFieldCreateDeleteWithExistingEntities() {
        ->fields($values)
        ->execute();
    }
      else {
        // Keep throwing it.
        throw $e;
      }
    }
  }

  /**