GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/sql.cc Lines: 41 74 55.4 %
Date: 2019-02-03 02:48:13 Branches: 9 32 28.1 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM file system.
3
 */
4
5
#include "cvmfs_config.h"
6
#include "sql.h"
7
8
#include "logging.h"
9
#include "util/string.h"
10
11
using namespace std;  // NOLINT
12
13
namespace sqlite {
14
15
2844
Sql::Sql(sqlite3 *sqlite_db, const std::string &statement)
16
  : database_(NULL)
17
  , statement_(NULL)
18
  , query_string_(NULL)
19
2844
  , last_error_code_(0)
20
{
21
2844
  Init(sqlite_db, statement);
22
2844
}
23
24
25
8464
Sql::~Sql() {
26
6634
  last_error_code_ = sqlite3_finalize(statement_);
27
28
6634
  if (!Successful()) {
29
    LogCvmfs(kLogSql, kLogDebug,
30
6
             "failed to finalize statement - error code: %d", last_error_code_);
31
  }
32
6634
  LogCvmfs(kLogSql, kLogDebug, "successfully finalized statement");
33
8464
}
34
35
36
/**
37
 * Executes the prepared statement.
38
 * (this method should be used for modifying statements like DELETE or INSERT)
39
 * @return true on success otherwise false
40
 */
41
159272
bool Sql::Execute() {
42
159272
  LazyInit();
43
159272
  last_error_code_ = sqlite3_step(statement_);
44
#ifdef DEBUGMSG
45
159272
  if (!Successful()) {
46
    LogCvmfs(kLogSql, kLogDebug, "SQL query failed - SQLite: %d - %s",
47
6
             GetLastError(), GetLastErrorMsg().c_str());
48
  }
49
#endif
50
159272
  return Successful();
51
}
52
53
54
/**
55
 * Execute the prepared statement or fetch its next row.
56
 * This method is intended to step through the result set.
57
 * If it returns false this does not neccessarily mean, that the actual
58
 * statement execution failed, but that no row was fetched.
59
 * @return true if a new row was fetched otherwise false
60
 */
61
8124
bool Sql::FetchRow() {
62
8124
  LazyInit();
63
8124
  last_error_code_ = sqlite3_step(statement_);
64
8124
  return SQLITE_ROW == last_error_code_;
65
}
66
67
68
std::string Sql::DebugResultTable() {
69
  std::string line;
70
  std::string result;
71
  unsigned int rows = 0;
72
73
  // go through all data rows
74
  while (FetchRow()) {
75
    // retrieve the table header (once)
76
    const unsigned int cols = sqlite3_column_count(statement_);
77
    if (rows == 0) {
78
      for (unsigned int col = 0; col < cols; ++col) {
79
        const char *name = sqlite3_column_name(statement_, col);
80
        line += name;
81
        if (col + 1 < cols) line += " | ";
82
      }
83
      result += line + "\n";
84
      line.clear();
85
    }
86
87
    // retrieve the data fields for each row
88
    for (unsigned int col = 0; col < cols; ++col) {
89
      const int type = sqlite3_column_type(statement_, col);
90
      switch (type) {
91
        case SQLITE_INTEGER:
92
          line += StringifyInt(RetrieveInt64(col));
93
          break;
94
        case SQLITE_FLOAT:
95
          line += StringifyDouble(RetrieveDouble(col));
96
          break;
97
        case SQLITE_TEXT:
98
          line += reinterpret_cast<const char *>(RetrieveText(col));
99
          break;
100
        case SQLITE_BLOB:
101
          line += "[BLOB data]";
102
          break;
103
        case SQLITE_NULL:
104
          line += "[NULL]";
105
          break;
106
      }
107
      if (col + 1 < cols) line += " | ";
108
    }
109
110
    result += line + "\n";
111
    line.clear();
112
    ++rows;
113
  }
114
115
  // print the result
116
  result += "Retrieved Rows: " + StringifyInt(rows);
117
  return result;
118
}
119
120
121
/**
122
 * Reset a prepared statement to make it reusable.
123
 * @return true on success otherwise false
124
 */
125
162401
bool Sql::Reset() {
126
162401
  last_error_code_ = sqlite3_reset(statement_);
127
162401
  return Successful();
128
}
129
130
131
3535
bool Sql::Init(const sqlite3 *database, const std::string &statement) {
132
3535
  database_ = const_cast<sqlite3 *>(database);
133
3535
  return Init(statement.c_str());
134
}
135
136
4092
bool Sql::Init(const char *statement) {
137
4092
  assert(NULL == statement_);
138
4092
  assert(NULL != database_);
139
140
  last_error_code_ = sqlite3_prepare_v2(database_,
141
                                        statement,
142
                                        -1,  // parse until null termination
143
                                        &statement_,
144
4092
                                        NULL);
145
146
4092
  if (!Successful()) {
147
    LogCvmfs(kLogSql, kLogDebug, "failed to prepare statement '%s' (%d: %s)",
148
             statement, GetLastError(), sqlite3_errmsg(database_));
149
    return false;
150
  }
151
152
  LogCvmfs(kLogSql, kLogDebug, "successfully prepared statement '%s'",
153
4092
           statement);
154
4092
  return true;
155
}
156
157
3110
void Sql::DeferredInit(const sqlite3 *database, const char *statement) {
158
3110
  assert(NULL == database_);
159
3110
  database_     = const_cast<sqlite3 *>(database);
160
3110
  query_string_ = statement;
161
3110
}
162
163
6
std::string Sql::GetLastErrorMsg() const {
164
6
  std::string msg = sqlite3_errmsg(database_);
165
6
  return msg;
166
}
167
168
}  // namespace sqlite