Unverified Commit 8ba2f05e authored by Alex Pott's avatar Alex Pott
Browse files

task: #3586760 Use composite key Upsert queries in core

By: mondrake
By: catch
By: amateescu
parent cc1edd29
Loading
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -164,9 +164,13 @@ public function write($name, array $data) {
   *   TRUE when the write was successful, FALSE otherwise.
   */
  protected function doWrite($name, $data) {
    return (bool) $this->connection->merge($this->table, $this->options)
      ->keys(['collection', 'name'], [$this->collection, $name])
      ->fields(['data' => $data])
    return (bool) $this->connection->upsert($this->table, $this->options)
      ->key(['collection', 'name'])
      ->fields([
        'collection' => $this->collection,
        'name' => $name,
        'data' => $data,
      ])
      ->execute();
  }

+50 −9
Original line number Diff line number Diff line
@@ -150,12 +150,13 @@ public function getAllKeys(): iterable {
   *   The data to store.
   */
  protected function doSet($key, $value) {
    $this->connection->merge($this->table)
      ->keys([
        'name' => $key,
    $this->connection->upsert($this->table)
      ->key(['collection', 'name'])
      ->fields([
        'collection' => $this->collection,
        'name' => $key,
        'value' => $this->serializer->encode($value),
      ])
      ->fields(['value' => $this->serializer->encode($value)])
      ->execute();
  }

@@ -177,17 +178,57 @@ public function set($key, $value) {
    }
  }

  /**
   * Saves key/value pairs.
   *
   * This will be called by ::setMultiple() within a try block.
   *
   * @param array $data
   *   An associative array of key/value pairs.
   */
  protected function doSetMultiple(array $data): void {
    $query = $this->connection->upsert($this->table)
      ->key(['collection', 'name']);

    $fieldsSet = FALSE;
    foreach ($data as $key => $value) {
      if (!$fieldsSet) {
        $query->fields([
          'collection' => $this->collection,
          'name' => $key,
          'value' => $this->serializer->encode($value),
        ]);
        $fieldsSet = TRUE;
        continue;
      }
      $query->values([
        'collection' => $this->collection,
        'name' => $key,
        'value' => $this->serializer->encode($value),
      ]);
    }

    $query->execute();
  }

  /**
   * {@inheritdoc}
   */
  public function setMultiple(array $data): void {
    $transaction = $this->connection->startTransaction();
    if (empty($data)) {
      return;
    }
    try {
      parent::setMultiple($data);
      $transaction->commitOrRelease();
      $this->doSetMultiple($data);
    }
    catch (\Exception $e) {
      // If there was an exception, try to create the table.
      if ($this->ensureTableExists()) {
        $this->doSetMultiple($data);
      }
      else {
        throw $e;
      }
    catch (\Exception) {
      $transaction->rollback();
    }
  }

+4 −5
Original line number Diff line number Diff line
@@ -130,12 +130,11 @@ public function getAllKeys(): iterable {
   *   The time to live for items, in seconds.
   */
  protected function doSetWithExpire($key, $value, $expire) {
    $this->connection->merge($this->table)
      ->keys([
        'name' => $key,
        'collection' => $this->collection,
      ])
    $this->connection->upsert($this->table)
      ->key(['collection', 'name'])
      ->fields([
        'collection' => $this->collection,
        'name' => $key,
        'value' => $this->serializer->encode($value),
        'expire' => $this->time->getRequestTime() + $expire,
      ])
+6 −6
Original line number Diff line number Diff line
@@ -66,16 +66,16 @@ public function doRead(#[\SensitiveParameter] string $sessionId): string {
  public function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool {
    $try_again = FALSE;
    $request = $this->requestStack->getCurrentRequest();
    $fields = [
    $doWrite = fn() =>
      $this->connection->upsert('sessions')
        ->key('sid')
        ->fields([
          'sid' => Crypt::hashBase64($sessionId),
          'uid' => $request->getSession()->get('uid', 0),
          'hostname' => $request->getClientIP(),
          'session' => $data,
          'timestamp' => $this->time->getRequestTime(),
    ];
    $doWrite = fn() =>
      $this->connection->merge('sessions')
        ->keys(['sid' => Crypt::hashBase64($sessionId)])
        ->fields($fields)
        ])
        ->execute();
    try {
      $doWrite();
+6 −7
Original line number Diff line number Diff line
@@ -233,20 +233,19 @@ public function update(CommentInterface $comment) {
        ->range(0, 1)
        ->execute()
        ->fetchObject();
      // Use merge here because entity could be created before comment field.
      $this->database->merge('comment_entity_statistics')
      // Use upsert here because entity could be created before comment field.
      $this->database->upsert('comment_entity_statistics')
        ->key(['entity_id', 'entity_type', 'field_name'])
        ->fields([
          'entity_id' => $comment->getCommentedEntityId(),
          'entity_type' => $comment->getCommentedEntityTypeId(),
          'field_name' => $comment->getFieldName(),
          'cid' => $last_reply->cid,
          'comment_count' => $count,
          'last_comment_timestamp' => $last_reply->changed,
          'last_comment_name' => $last_reply->uid ? '' : $last_reply->name,
          'last_comment_uid' => $last_reply->uid,
        ])
        ->keys([
          'entity_id' => $comment->getCommentedEntityId(),
          'entity_type' => $comment->getCommentedEntityTypeId(),
          'field_name' => $comment->getFieldName(),
        ])
        ->execute();
    }
    else {
Loading