Insert::execute

public Insert::execute()

Executes the insert query.

Return value

The last insert ID of the query, if one exists. If the query was given multiple sets of values to insert, the return value is undefined. If no fields are specified, this method will do nothing and return NULL. That That makes it safe to use in multi-insert loops.

Overrides Insert::execute

File

core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php, line 18

Class

Insert
PostgreSQL implementation of \Drupal\Core\Database\Query\Insert.

Namespace

Drupal\Core\Database\Driver\pgsql

Code

public function execute() {
  if (!$this->preExecute()) {
    return NULL;
  }

  $stmt = $this->connection->prepareQuery((string) $this);

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

  $max_placeholder = 0;
  $blobs = array();
  $blob_count = 0;
  foreach ($this->insertValues as $insert_values) {
    foreach ($this->insertFields as $idx => $field) {
      if (isset($table_information->blob_fields[$field])) {
        $blobs[$blob_count] = fopen('php://memory', 'a');
        fwrite($blobs[$blob_count], $insert_values[$idx]);
        rewind($blobs[$blob_count]);

        $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $blobs[$blob_count], \PDO::PARAM_LOB);

        // Pre-increment is faster in PHP than increment.
        ++$blob_count;
      }
      else {
        $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $insert_values[$idx]);
      }
    }
    // Check if values for a serial field has been passed.
    if (!empty($table_information->serial_fields)) {
      foreach ($table_information->serial_fields as $index => $serial_field) {
        $serial_key = array_search($serial_field, $this->insertFields);
        if ($serial_key !== FALSE) {
          $serial_value = $insert_values[$serial_key];

          // Force $last_insert_id to the specified value. This is only done
          // if $index is 0.
          if ($index == 0) {
            $last_insert_id = $serial_value;
          }
          // Sequences must be greater than or equal to 1.
          if ($serial_value === NULL || !$serial_value) {
            $serial_value = 1;
          }
          // Set the sequence to the bigger value of either the passed
          // value or the max value of the column. It can happen that another
          // thread calls nextval() which could lead to a serial number being
          // used twice. However, trying to insert a value into a serial
          // column should only be done in very rare cases and is not thread
          // safe by definition.
          $this->connection->query("SELECT setval('" . $table_information->sequences[$index] . "', GREATEST(MAX(" . $serial_field . "), :serial_value)) FROM {" . $this->table . "}", array(':serial_value' => (int) $serial_value));
        }
      }
    }
  }
  if (!empty($this->fromQuery)) {
    // bindParam stores only a reference to the variable that is followed when
    // the statement is executed. We pass $arguments[$key] instead of $value
    // because the second argument to bindParam is passed by reference and
    // the foreach statement assigns the element to the existing reference.
    $arguments = $this->fromQuery->getArguments();
    foreach ($arguments as $key => $value) {
      $stmt->bindParam($key, $arguments[$key]);
    }
  }

  // PostgreSQL requires the table name to be specified explicitly
  // when requesting the last insert ID, so we pass that in via
  // the options array.
  $options = $this->queryOptions;

  if (!empty($table_information->sequences)) {
    $options['sequence_name'] = $table_information->sequences[0];
  }
  // If there are no sequences then we can't get a last insert id.
  elseif ($options['return'] == Database::RETURN_INSERT_ID) {
    $options['return'] = Database::RETURN_NULL;
  }

  // Create a savepoint so we can rollback a failed query. This is so we can
  // mimic MySQL and SQLite transactions which don't fail if a single query
  // fails. This is important for tables that are created on demand. For
  // example, \Drupal\Core\Cache\DatabaseBackend.
  $this->connection->addSavepoint();
  try {
    // Only use the returned last_insert_id if it is not already set.
    if (!empty($last_insert_id)) {
      $this->connection->query($stmt, array(), $options);
    }
    else {
      $last_insert_id = $this->connection->query($stmt, array(), $options);
    }
    $this->connection->releaseSavepoint();
  }
  catch (\Exception $e) {
    $this->connection->rollbackSavepoint();
    throw $e;
  }

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

  return $last_insert_id;
}
doc_Drupal
2016-10-29 09:20:42
Comments
Leave a Comment

Please login to continue.