You are here

public function Upsert::__toString in Drupal driver for SQL Server and SQL Azure 8.2

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

Implements PHP magic __toString method to convert the query to a string.

The toString operation is how we compile a query object to a prepared statement.

Return value

string A prepared statement query string for this object.

Overrides Query::__toString

File

drivers/lib/Drupal/Driver/Database/sqlsrv/Upsert.php, line 74
Contains \Drupal\Core\Database\Driver\sqlsrv\Upsert

Class

Upsert
Implements Native Upsert queries for MSSQL.

Namespace

Drupal\Driver\Database\sqlsrv

Code

public function __toString() {

  // Fetch the list of blobs and sequences used on that table.
  $columnInformation = $this->connection
    ->schema()
    ->getTableIntrospection($this->table);

  // Find out if there is an identity field set in this insert.
  $setIdentity = !empty($columnInformation['identity']) && in_array($columnInformation['identity'], array_keys($this->insertFields));
  $query = [];
  $real_table = $this->connection
    ->prefixTable($this->table);

  // Enable direct insertion to identity columns if necessary.
  if ($setIdentity === true) {
    $query[] = "SET IDENTITY_INSERT [{$real_table}] ON;";
  }
  $query[] = "MERGE INTO [{$real_table}] _target";

  // 1. Implicit dataset
  // select t.*  from (values(1,2,3), (2,3,4)) as t(col1,col2,col3)
  $values = $this
    ->getInsertPlaceholderFragment($this->insertValues, $this->defaultFields);
  $columns = implode(', ', $this->connection
    ->quoteIdentifiers($this->insertFields));
  $dataset = "SELECT T.* FROM (values" . implode(',', $values) . ") as T({$columns})";

  // Build primery key conditions
  $key_conditions = [];

  // Fetch the list of blobs and sequences used on that table.
  $primary_key_cols = array_column($columnInformation['indexes'][$columnInformation['primary_key_index']]['columns'], 'name');
  foreach ($primary_key_cols as $key) {
    $key_conditions[] = "_target.[{$key}] = _source.[{$key}]";
  }
  $query[] = "USING ({$dataset}) _source" . PHP_EOL . 'ON ' . implode(' AND ', $key_conditions);

  // Mappings.
  $insert_mappings = [];
  $update_mappings = [];
  foreach ($this->insertFields as $field) {
    $insert_mappings[] = "_source.[{$field}]";

    // Updating the unique / primary key is not necessary.
    if (!in_array($field, $primary_key_cols)) {
      $update_mappings[] = "_target.[{$field}] = _source.[{$field}]";
    }
  }

  // "When matched" part
  $query[] = 'WHEN MATCHED THEN UPDATE SET ' . implode(', ', $update_mappings);

  // "When not matched" part.
  $query[] = "WHEN NOT MATCHED THEN INSERT ({$columns}) VALUES (" . implode(', ', $insert_mappings) . ")";

  // Return information about the query.
  $query[] = 'OUTPUT $action;';
  return implode(PHP_EOL, $query);
}