File: database_string_table.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (121 lines) | stat: -rw-r--r-- 3,995 bytes parent folder | download | duplicates (6)
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
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/activity_log/database_string_table.h"

#include <stddef.h>

#include "base/strings/strcat.h"
#include "sql/database.h"
#include "sql/statement.h"

namespace extensions {

// A target maximum size (in number of entries) for the mapping tables.  If the
// cache would grow larger than this, the size should be reduced.
static const size_t kMaximumCacheSize = 1000;

DatabaseStringTable::DatabaseStringTable(const std::string& table)
    : table_(table) {}

DatabaseStringTable::~DatabaseStringTable() = default;

bool DatabaseStringTable::Initialize(sql::Database* connection) {
  if (!connection->DoesTableExist(table_.c_str())) {
    return connection->Execute(base::StrCat(
               {"CREATE TABLE ", table_,
                "(id INTEGER PRIMARY KEY, value TEXT NOT NULL)"})) &&
           connection->Execute(base::StrCat({"CREATE UNIQUE INDEX ", table_,
                                             "_index ON ", table_, "(value)"}));
  }
  return true;
}

bool DatabaseStringTable::StringToInt(sql::Database* connection,
                                      const std::string& value,
                                      int64_t* id) {
  std::map<std::string, int64_t>::const_iterator lookup =
      value_to_id_.find(value);
  if (lookup != value_to_id_.end()) {
    *id = lookup->second;
    return true;
  }

  // We will be adding data to the cache below--check the cache size now and
  // reduce it if needed.
  PruneCache();

  // Operate on the assumption that the cache does a good job on
  // frequently-used strings--if there is a cache miss, first act on the
  // assumption that the string is not in the database either.
  sql::Statement update(connection->GetUniqueStatement(
      base::StrCat({"INSERT OR IGNORE INTO ", table_, "(value) VALUES (?)"})));
  update.BindString(0, value);
  if (!update.Run())
    return false;

  if (connection->GetLastChangeCount() == 1) {
    *id = connection->GetLastInsertRowId();
    id_to_value_[*id] = value;
    value_to_id_[value] = *id;
    return true;
  }

  // The specified string may have already existed in the database, in which
  // case the insert above will have been ignored.  If this happens, do a
  // lookup to find the old value.
  sql::Statement query(connection->GetUniqueStatement(
      base::StrCat({"SELECT id FROM ", table_, " WHERE value = ?"})));
  query.BindString(0, value);
  if (!query.Step())
    return false;
  *id = query.ColumnInt64(0);
  id_to_value_[*id] = value;
  value_to_id_[value] = *id;
  return true;
}

bool DatabaseStringTable::IntToString(sql::Database* connection,
                                      int64_t id,
                                      std::string* value) {
  std::map<int64_t, std::string>::const_iterator lookup = id_to_value_.find(id);
  if (lookup != id_to_value_.end()) {
    *value = lookup->second;
    return true;
  }

  // We will be adding data to the cache below--check the cache size now and
  // reduce it if needed.
  PruneCache();

  sql::Statement query(connection->GetUniqueStatement(
      base::StrCat({"SELECT value FROM ", table_, " WHERE id = ?"})));
  query.BindInt64(0, id);
  if (!query.Step())
    return false;

  *value = query.ColumnString(0);
  id_to_value_[id] = *value;
  value_to_id_[*value] = id;
  return true;
}

void DatabaseStringTable::ClearCache() {
  id_to_value_.clear();
  value_to_id_.clear();
}

void DatabaseStringTable::PruneCache() {
  if (id_to_value_.size() <= kMaximumCacheSize &&
      value_to_id_.size() <= kMaximumCacheSize)
    return;

  // TODO(mvrable): Perhaps implement a more intelligent caching policy.  For
  // now, to limit memory usage we simply clear the entire cache when it would
  // become too large.  Data will be brought back in from the database as
  // needed.
  ClearCache();
}

}  // namespace extensions