Home | History | Annotate | Download | only in sql
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "sql/meta_table.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/string_util.h"
      9 #include "sql/connection.h"
     10 #include "sql/statement.h"
     11 #include "sql/transaction.h"
     12 
     13 namespace sql {
     14 
     15 // Key used in our meta table for version numbers.
     16 static const char kVersionKey[] = "version";
     17 static const char kCompatibleVersionKey[] = "last_compatible_version";
     18 
     19 MetaTable::MetaTable() : db_(NULL) {
     20 }
     21 
     22 MetaTable::~MetaTable() {
     23 }
     24 
     25 // static
     26 bool MetaTable::DoesTableExist(sql::Connection* db) {
     27   DCHECK(db);
     28   return db->DoesTableExist("meta");
     29 }
     30 
     31 bool MetaTable::Init(Connection* db, int version, int compatible_version) {
     32   DCHECK(!db_ && db);
     33   db_ = db;
     34 
     35   // If values stored are null or missing entirely, 0 will be reported.
     36   // Require new clients to start with a greater initial version.
     37   DCHECK_GT(version, 0);
     38   DCHECK_GT(compatible_version, 0);
     39 
     40   // Make sure the table is created an populated atomically.
     41   sql::Transaction transaction(db_);
     42   if (!transaction.Begin())
     43     return false;
     44 
     45   if (!DoesTableExist(db)) {
     46     if (!db_->Execute("CREATE TABLE meta"
     47         "(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR)"))
     48       return false;
     49 
     50     // Note: there is no index over the meta table. We currently only have a
     51     // couple of keys, so it doesn't matter. If we start storing more stuff in
     52     // there, we should create an index.
     53     SetVersionNumber(version);
     54     SetCompatibleVersionNumber(compatible_version);
     55   } else {
     56     db_->AddTaggedHistogram("Sqlite.Version", GetVersionNumber());
     57   }
     58   return transaction.Commit();
     59 }
     60 
     61 void MetaTable::Reset() {
     62   db_ = NULL;
     63 }
     64 
     65 void MetaTable::SetVersionNumber(int version) {
     66   DCHECK_GT(version, 0);
     67   SetValue(kVersionKey, version);
     68 }
     69 
     70 int MetaTable::GetVersionNumber() {
     71   int version = 0;
     72   return GetValue(kVersionKey, &version) ? version : 0;
     73 }
     74 
     75 void MetaTable::SetCompatibleVersionNumber(int version) {
     76   DCHECK_GT(version, 0);
     77   SetValue(kCompatibleVersionKey, version);
     78 }
     79 
     80 int MetaTable::GetCompatibleVersionNumber() {
     81   int version = 0;
     82   return GetValue(kCompatibleVersionKey, &version) ? version : 0;
     83 }
     84 
     85 bool MetaTable::SetValue(const char* key, const std::string& value) {
     86   Statement s;
     87   PrepareSetStatement(&s, key);
     88   s.BindString(1, value);
     89   return s.Run();
     90 }
     91 
     92 bool MetaTable::SetValue(const char* key, int value) {
     93   Statement s;
     94   PrepareSetStatement(&s, key);
     95   s.BindInt(1, value);
     96   return s.Run();
     97 }
     98 
     99 bool MetaTable::SetValue(const char* key, int64 value) {
    100   Statement s;
    101   PrepareSetStatement(&s, key);
    102   s.BindInt64(1, value);
    103   return s.Run();
    104 }
    105 
    106 bool MetaTable::GetValue(const char* key, std::string* value) {
    107   Statement s;
    108   if (!PrepareGetStatement(&s, key))
    109     return false;
    110 
    111   *value = s.ColumnString(0);
    112   return true;
    113 }
    114 
    115 bool MetaTable::GetValue(const char* key, int* value) {
    116   Statement s;
    117   if (!PrepareGetStatement(&s, key))
    118     return false;
    119 
    120   *value = s.ColumnInt(0);
    121   return true;
    122 }
    123 
    124 bool MetaTable::GetValue(const char* key, int64* value) {
    125   Statement s;
    126   if (!PrepareGetStatement(&s, key))
    127     return false;
    128 
    129   *value = s.ColumnInt64(0);
    130   return true;
    131 }
    132 
    133 bool MetaTable::DeleteKey(const char* key) {
    134   DCHECK(db_);
    135   Statement s(db_->GetUniqueStatement("DELETE FROM meta WHERE key=?"));
    136   s.BindCString(0, key);
    137   return s.Run();
    138 }
    139 
    140 void MetaTable::PrepareSetStatement(Statement* statement, const char* key) {
    141   DCHECK(db_ && statement);
    142   statement->Assign(db_->GetCachedStatement(SQL_FROM_HERE,
    143       "INSERT OR REPLACE INTO meta (key,value) VALUES (?,?)"));
    144   statement->BindCString(0, key);
    145 }
    146 
    147 bool MetaTable::PrepareGetStatement(Statement* statement, const char* key) {
    148   DCHECK(db_ && statement);
    149   statement->Assign(db_->GetCachedStatement(SQL_FROM_HERE,
    150       "SELECT value FROM meta WHERE key=?"));
    151   statement->BindCString(0, key);
    152   return statement->Step();
    153 }
    154 
    155 }  // namespace sql
    156