You are here

public function Upsert::execute in Drupal driver for SQL Server and SQL Azure 8

Same name and namespace in other branches
  1. 8.2 drivers/lib/Drupal/Driver/Database/sqlsrv/Upsert.php \Drupal\Driver\Database\sqlsrv\Upsert::execute()
  2. 3.0.x drivers/lib/Drupal/Driver/Database/sqlsrv/Upsert.php \Drupal\Driver\Database\sqlsrv\Upsert::execute()

Runs the query against the database.

Return value

\Drupal\Core\Database\StatementInterface|null A prepared statement, or NULL if the query is not valid.

Overrides Upsert::execute

File

drivers/lib/Drupal/Driver/Database/sqlsrv/Upsert.php, line 17

Class

Upsert
Implements Native Upsert queries for MSSQL.

Namespace

Drupal\Driver\Database\sqlsrv

Code

public function execute() {
  if (count($this->insertValues) === 1) {
    $insert_fields = array_merge($this->defaultFields, $this->insertFields);
    $update_fields = array_combine($insert_fields, array_shift($this->insertValues));
    $condition = $update_fields[$this->key];
    $merge = $this->connection
      ->merge($this->table, $this->queryOptions)
      ->fields($update_fields)
      ->key($this->key, $condition);
    $merge
      ->execute();
    return NULL;
  }
  if (!$this
    ->preExecute()) {
    return NULL;
  }

  // Fetch the list of blobs and sequences used on that table.

  /** @var \Drupal\Driver\Database\sqlsrv\Schema $schema */
  $schema = $this->connection
    ->schema();
  $columnInformation = $schema
    ->queryColumnInformation($this->table);
  $this->queryOptions['allow_delimiter_in_query'] = TRUE;
  $max_placeholder = -1;
  $values = [];
  foreach ($this->insertValues as $insert_values) {
    foreach ($insert_values as $value) {
      $values[':db_upsert_placeholder_' . ++$max_placeholder] = $value;
    }
  }
  $batch = array_splice($this->insertValues, 0, min(intdiv(2000, count($this->insertFields)), self::MAX_BATCH_SIZE));

  // If we are going to need more than one batch for this, start a
  // transaction.
  if (empty($this->queryOptions['sqlsrv_skip_transactions']) && !empty($this->insertValues)) {
    $transaction = $this->connection
      ->startTransaction();
  }
  while (!empty($batch)) {

    // Give me a query with the amount of batch inserts.
    $query = $this
      ->buildQuery(count($batch));

    // Prepare the query.

    /** @var \Drupal\Core\Database\Statement $stmt */
    $stmt = $this->connection
      ->prepareQuery($query);

    // We use this array to store references to the blob handles.
    // This is necessary because the PDO will otherwise mess up with
    // references.
    $blobs = [];
    $max_placeholder = 0;
    foreach ($batch as $insert_index => $insert_values) {
      $values = array_combine($this->insertFields, $insert_values);
      Utils::bindValues($stmt, $values, $blobs, ':db_upsert_placeholder_', $columnInformation, $max_placeholder, $insert_index);
    }

    // Run the query.
    $this->connection
      ->query($stmt, [], $this->queryOptions);

    // Fetch the next batch.
    $batch = array_splice($this->insertValues, 0, min(intdiv(2000, count($this->insertFields)), self::MAX_BATCH_SIZE));
  }

  // Re-initialize the values array so that we can re-use this query.
  $this->insertValues = [];
  return NULL;
}