You are here

class InsertQuery_sqlsrv in Drupal driver for SQL Server and SQL Azure 7

Same name and namespace in other branches
  1. 7.3 sqlsrv/query.inc \InsertQuery_sqlsrv
  2. 7.2 sqlsrv/query.inc \InsertQuery_sqlsrv

SQL Server-specific implementation of INSERT.

SQL Server doesn't supports multi-insert queries, and needs special handling for binary columns.

Hierarchy

Expanded class hierarchy of InsertQuery_sqlsrv

File

sqlsrv/query.inc, line 9

View source
class InsertQuery_sqlsrv extends InsertQuery {
  public function execute() {
    if (!$this
      ->preExecute()) {
      return NULL;
    }

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

    // Find out if there is an identity field set in this insert.
    foreach ($this->insertFields as $field) {
      if (isset($columnInformation['identities'][$field])) {
        $this->setIdentity = TRUE;
      }
    }

    // Each insert happens in its own query. However, we wrap it in a transaction
    // so that it is atomic where possible.
    if (empty($this->queryOptions['sqlsrv_skip_transactions'])) {
      $transaction = $this->connection
        ->startTransaction();
    }
    if (!empty($this->fromQuery)) {

      // Re-initialize the values array so that we can re-use this query.
      $this->insertValues = array();
      $stmt = $this->connection
        ->PDOPrepare($this->connection
        ->prefixTables((string) $this));

      // Handle the case of SELECT-based INSERT queries first.
      $values = $this->fromQuery
        ->getArguments();
      foreach ($values as $key => $value) {
        $stmt
          ->bindParam($key, $values[$key]);
      }
      try {
        $stmt
          ->execute();
      } catch (Exception $e) {

        // This INSERT query failed, rollback everything if we started a transaction earlier.
        if (!empty($transaction)) {
          $transaction
            ->rollback();
        }

        // Rethrow the exception.
        throw $e;
      }
      return $this->connection
        ->lastInsertId();
    }

    // Handle the case of full-default queries.
    if (empty($this->fromQuery) && (empty($this->insertFields) || empty($this->insertValues))) {

      // Re-initialize the values array so that we can re-use this query.
      $this->insertValues = array();
      $stmt = $this->connection
        ->PDOPrepare($this->connection
        ->prefixTables('INSERT INTO {' . $this->table . '} DEFAULT VALUES'));
      try {
        $stmt
          ->execute();
      } catch (Exception $e) {

        // This INSERT query failed, rollback everything if we started a transaction earlier.
        if (!empty($transaction)) {
          $transaction
            ->rollback();
        }

        // Rethrow the exception.
        throw $e;
      }
      return $this->connection
        ->lastInsertId();
    }
    $query = (string) $this;
    $stmt = $this->connection
      ->PDOPrepare($this->connection
      ->prefixTables($query));

    // We use this array to store references to the blob handles.
    // This is necessary because the PDO will otherwise messes up with references.
    $data_values = array();
    foreach ($this->insertValues as $insert_index => $insert_values) {
      $max_placeholder = 0;
      foreach ($this->insertFields as $field_index => $field) {
        $placeholder = ':db_insert' . $max_placeholder++;
        if (isset($columnInformation['blobs'][$field])) {
          $data_values[$placeholder . $insert_index] = fopen('php://memory', 'a');
          fwrite($data_values[$placeholder . $insert_index], $insert_values[$field_index]);
          rewind($data_values[$placeholder . $insert_index]);
          $stmt
            ->bindParam($placeholder, $data_values[$placeholder . $insert_index], PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
        }
        else {
          $data_values[$placeholder . $insert_index] = $insert_values[$field_index];
          $stmt
            ->bindParam($placeholder, $data_values[$placeholder . $insert_index]);
        }
      }
      try {
        $stmt
          ->execute();
      } catch (Exception $e) {

        // This INSERT query failed, rollback everything if we started a transaction earlier.
        if (!empty($transaction)) {
          $transaction
            ->rollback();
        }

        // Rethrow the exception.
        throw $e;
      }
      $last_insert_id = $this->connection
        ->lastInsertId();
    }

    // Re-initialize the values array so that we can re-use this query.
    $this->insertValues = array();
    return $last_insert_id;
  }
  public function __toString() {

    // Create a sanitized comment string to prepend to the query.
    $prefix = $this->connection
      ->makeComment($this->comments);

    // Enable direct insertion to identity columns if necessary.
    if (!empty($this->setIdentity)) {
      $prefix .= 'SET IDENTITY_INSERT {' . $this->table . '} ON;';
    }

    // If we're selecting from a SelectQuery, finish building the query and
    // pass it back, as any remaining options are irrelevant.
    if (!empty($this->fromQuery)) {
      return $prefix . "INSERT INTO {" . $this->table . '} (' . implode(', ', $this->connection
        ->quoteIdentifiers($this->insertFields)) . ') ' . $this->fromQuery;
    }

    // Build the list of placeholders.
    $placeholders = array();
    for ($i = 0; $i < count($this->insertFields); ++$i) {
      $placeholders[] = ':db_insert' . $i;
    }
    return $prefix . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->connection
      ->quoteIdentifiers($this->insertFields)) . ') VALUES (' . implode(', ', $placeholders) . ')';
  }

}

Members

Namesort descending Modifiers Type Description Overrides
InsertQuery::$defaultFields protected property An array of fields that should be set to their database-defined defaults.
InsertQuery::$fromQuery protected property A SelectQuery object to fetch the rows that should be inserted.
InsertQuery::$insertFields protected property An array of fields on which to insert.
InsertQuery::$insertValues protected property A nested array of values to insert.
InsertQuery::$table protected property The table on which to insert.
InsertQuery::fields public function Adds a set of field->value pairs to be inserted.
InsertQuery::from public function Sets the fromQuery on this InsertQuery object.
InsertQuery::preExecute public function Preprocesses and validates the query.
InsertQuery::useDefaults public function Specifies fields for which the database defaults should be used.
InsertQuery::values public function Adds another set of values to the query to be inserted.
InsertQuery::__construct public function Constructs an InsertQuery object. Overrides Query::__construct
InsertQuery_sqlsrv::execute public function Executes the insert query. Overrides InsertQuery::execute
InsertQuery_sqlsrv::__toString public function Implements PHP magic __toString method to convert the query to a string. Overrides InsertQuery::__toString
Query::$comments protected property An array of comments that can be prepended to a query.
Query::$connection protected property The connection object on which to run this query.
Query::$connectionKey protected property The key of the connection object.
Query::$connectionTarget protected property The target of the connection object.
Query::$nextPlaceholder protected property The placeholder counter.
Query::$queryOptions protected property The query options to pass on to the connection object.
Query::$uniqueIdentifier protected property A unique identifier for this query object.
Query::comment public function Adds a comment to the query.
Query::getComments public function Returns a reference to the comments array for the query.
Query::nextPlaceholder public function Gets the next placeholder value for this query object. Overrides QueryPlaceholderInterface::nextPlaceholder
Query::uniqueIdentifier public function Returns a unique identifier for this object. Overrides QueryPlaceholderInterface::uniqueIdentifier
Query::__clone public function Implements the magic __clone function. 1
Query::__sleep public function Implements the magic __sleep function to disconnect from the database.
Query::__wakeup public function Implements the magic __wakeup function to reconnect to the database.