DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (2f44d750d784)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_storage_StatementCache_h
#define mozilla_storage_StatementCache_h

#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "mozIStorageAsyncStatement.h"

#include "nsAutoPtr.h"
#include "nsHashKeys.h"
#include "nsInterfaceHashtable.h"

namespace mozilla {
namespace storage {

/**
 * Class used to cache statements (mozIStorageStatement or
 * mozIStorageAsyncStatement).
 */
template <typename StatementType>
class StatementCache {
 public:
  /**
   * Constructor for the cache.
   *
   * @note a connection can have more than one cache.
   *
   * @param aConnection
   *        A reference to the nsCOMPtr for the connection this cache is to be
   *        used for.  This nsCOMPtr must at least live as long as this class,
   *        otherwise crashes will happen.
   */
  explicit StatementCache(nsCOMPtr<mozIStorageConnection>& aConnection)
      : mConnection(aConnection) {}

  /**
   * Obtains a cached statement.  If this statement is not yet created, it will
   * be created and stored for later use.
   *
   * @param aQuery
   *        The SQL string (either a const char [] or nsACString) to get a
   *        cached query for.
   * @return the cached statement, or null upon error.
   */
  inline already_AddRefed<StatementType> GetCachedStatement(
      const nsACString& aQuery) {
    nsCOMPtr<StatementType> stmt;
    if (!mCachedStatements.Get(aQuery, getter_AddRefs(stmt))) {
      stmt = CreateStatement(aQuery);
      NS_ENSURE_TRUE(stmt, nullptr);

      mCachedStatements.Put(aQuery, stmt);
    }
    return stmt.forget();
  }

  template <int N>
  MOZ_ALWAYS_INLINE already_AddRefed<StatementType> GetCachedStatement(
      const char (&aQuery)[N]) {
    nsDependentCString query(aQuery, N - 1);
    return GetCachedStatement(query);
  }

  /**
   * Finalizes all cached statements so the database can be safely closed.  The
   * behavior of this cache is unspecified after this method is called.
   */
  inline void FinalizeStatements() {
    for (auto iter = mCachedStatements.Iter(); !iter.Done(); iter.Next()) {
      (void)iter.Data()->Finalize();
    }

    // Clear the cache at this time too!
    (void)mCachedStatements.Clear();
  }

 private:
  inline already_AddRefed<StatementType> CreateStatement(
      const nsACString& aQuery);

  nsInterfaceHashtable<nsCStringHashKey, StatementType> mCachedStatements;
  nsCOMPtr<mozIStorageConnection>& mConnection;
};

template <>
inline already_AddRefed<mozIStorageStatement>
StatementCache<mozIStorageStatement>::CreateStatement(
    const nsACString& aQuery) {
  NS_ENSURE_TRUE(mConnection, nullptr);

  nsCOMPtr<mozIStorageStatement> stmt;
  nsresult rv = mConnection->CreateStatement(aQuery, getter_AddRefs(stmt));
  if (NS_FAILED(rv)) {
    nsCString error;
    error.AppendLiteral("The statement '");
    error.Append(aQuery);
    error.AppendLiteral("' failed to compile with the error message '");
    nsCString msg;
    (void)mConnection->GetLastErrorString(msg);
    error.Append(msg);
    error.AppendLiteral("'.");
    NS_ERROR(error.get());
  }
  NS_ENSURE_SUCCESS(rv, nullptr);

  return stmt.forget();
}

template <>
inline already_AddRefed<mozIStorageAsyncStatement>
StatementCache<mozIStorageAsyncStatement>::CreateStatement(
    const nsACString& aQuery) {
  NS_ENSURE_TRUE(mConnection, nullptr);

  nsCOMPtr<mozIStorageAsyncStatement> stmt;
  nsresult rv = mConnection->CreateAsyncStatement(aQuery, getter_AddRefs(stmt));
  NS_ENSURE_SUCCESS(rv, nullptr);

  return stmt.forget();
}

}  // namespace storage
}  // namespace mozilla

#endif  // mozilla_storage_StatementCache_h