sqlite.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "sqlite.hh"
  2. #include "util.hh"
  3. #include <sqlite3.h>
  4. namespace nix {
  5. [[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f)
  6. {
  7. int err = sqlite3_errcode(db);
  8. if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) {
  9. if (err == SQLITE_PROTOCOL)
  10. printMsg(lvlError, "warning: SQLite database is busy (SQLITE_PROTOCOL)");
  11. else {
  12. static bool warned = false;
  13. if (!warned) {
  14. printMsg(lvlError, "warning: SQLite database is busy");
  15. warned = true;
  16. }
  17. }
  18. /* Sleep for a while since retrying the transaction right away
  19. is likely to fail again. */
  20. #if HAVE_NANOSLEEP
  21. struct timespec t;
  22. t.tv_sec = 0;
  23. t.tv_nsec = (random() % 100) * 1000 * 1000; /* <= 0.1s */
  24. nanosleep(&t, 0);
  25. #else
  26. sleep(1);
  27. #endif
  28. throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
  29. }
  30. else
  31. throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
  32. }
  33. SQLite::~SQLite()
  34. {
  35. try {
  36. if (db && sqlite3_close(db) != SQLITE_OK)
  37. throwSQLiteError(db, "closing database");
  38. } catch (...) {
  39. ignoreException();
  40. }
  41. }
  42. void SQLiteStmt::create(sqlite3 * db, const string & s)
  43. {
  44. checkInterrupt();
  45. assert(!stmt);
  46. if (sqlite3_prepare_v2(db, s.c_str(), -1, &stmt, 0) != SQLITE_OK)
  47. throwSQLiteError(db, "creating statement");
  48. this->db = db;
  49. }
  50. SQLiteStmt::~SQLiteStmt()
  51. {
  52. try {
  53. if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
  54. throwSQLiteError(db, "finalizing statement");
  55. } catch (...) {
  56. ignoreException();
  57. }
  58. }
  59. SQLiteStmt::Use::Use(SQLiteStmt & stmt)
  60. : stmt(stmt)
  61. {
  62. assert(stmt.stmt);
  63. /* Note: sqlite3_reset() returns the error code for the most
  64. recent call to sqlite3_step(). So ignore it. */
  65. sqlite3_reset(stmt);
  66. }
  67. SQLiteStmt::Use::~Use()
  68. {
  69. sqlite3_reset(stmt);
  70. }
  71. SQLiteStmt::Use & SQLiteStmt::Use::operator () (const std::string & value, bool notNull)
  72. {
  73. if (notNull) {
  74. if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
  75. throwSQLiteError(stmt.db, "binding argument");
  76. } else
  77. bind();
  78. return *this;
  79. }
  80. SQLiteStmt::Use & SQLiteStmt::Use::operator () (int64_t value, bool notNull)
  81. {
  82. if (notNull) {
  83. if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
  84. throwSQLiteError(stmt.db, "binding argument");
  85. } else
  86. bind();
  87. return *this;
  88. }
  89. SQLiteStmt::Use & SQLiteStmt::Use::bind()
  90. {
  91. if (sqlite3_bind_null(stmt, curArg++) != SQLITE_OK)
  92. throwSQLiteError(stmt.db, "binding argument");
  93. return *this;
  94. }
  95. int SQLiteStmt::Use::step()
  96. {
  97. return sqlite3_step(stmt);
  98. }
  99. void SQLiteStmt::Use::exec()
  100. {
  101. int r = step();
  102. assert(r != SQLITE_ROW);
  103. if (r != SQLITE_DONE)
  104. throwSQLiteError(stmt.db, "executing SQLite statement");
  105. }
  106. bool SQLiteStmt::Use::next()
  107. {
  108. int r = step();
  109. if (r != SQLITE_DONE && r != SQLITE_ROW)
  110. throwSQLiteError(stmt.db, "executing SQLite query");
  111. return r == SQLITE_ROW;
  112. }
  113. std::string SQLiteStmt::Use::getStr(int col)
  114. {
  115. auto s = (const char *) sqlite3_column_text(stmt, col);
  116. assert(s);
  117. return s;
  118. }
  119. int64_t SQLiteStmt::Use::getInt(int col)
  120. {
  121. // FIXME: detect nulls?
  122. return sqlite3_column_int64(stmt, col);
  123. }
  124. SQLiteTxn::SQLiteTxn(sqlite3 * db)
  125. {
  126. this->db = db;
  127. if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
  128. throwSQLiteError(db, "starting transaction");
  129. active = true;
  130. }
  131. void SQLiteTxn::commit()
  132. {
  133. if (sqlite3_exec(db, "commit;", 0, 0, 0) != SQLITE_OK)
  134. throwSQLiteError(db, "committing transaction");
  135. active = false;
  136. }
  137. SQLiteTxn::~SQLiteTxn()
  138. {
  139. try {
  140. if (active && sqlite3_exec(db, "rollback;", 0, 0, 0) != SQLITE_OK)
  141. throwSQLiteError(db, "aborting transaction");
  142. } catch (...) {
  143. ignoreException();
  144. }
  145. }
  146. }