SHARE
TWEET

Untitled

a guest Jan 11th, 2017 68 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "sqlite3.h"
  2. #include <thread>
  3. #include <cstdlib> // for rand()
  4. #include <string>
  5. #include <vector>
  6. #include <iostream>
  7.  
  8. using std::string;
  9. using std::cerr;
  10. using std::endl;
  11.  
  12. const int NUM_THREADS = 3;
  13. const int ROWS_PER_THREAD = 10;
  14.  
  15. #define TEST(x) do{cerr<<(x?"PASSED ":"FAILED ")<< #x <<endl;} while(0)
  16.  
  17. class connection {
  18. public:
  19.     explicit connection(string dbpath) : dbpath_(dbpath) { open(); }
  20.     virtual ~connection() { sqlite3_close(db_); }
  21.     operator sqlite3*() { return db_; }
  22.     int exec(string sql) {return sqlite3_exec(db_, sql.c_str(), 0, 0, 0);}
  23. private:
  24.     int open() {
  25.         int const flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  26.         return sqlite3_open_v2(dbpath_.c_str(), &db_, flags, 0);
  27.     }
  28.     string const dbpath_;
  29.     sqlite3* db_;
  30. };
  31.  
  32. class statement {
  33. public:
  34.     statement(sqlite3* db, string sql) : db_(db), sql_(sql) {prepare();}
  35.     virtual ~statement() { sqlite3_finalize(stmt_); }
  36.     operator sqlite3_stmt*() { return stmt_; }
  37.     int column_int(int col) {return sqlite3_column_int(stmt_, col);}
  38.     int step() { return sqlite3_step(stmt_); }
  39.     int bind(int i, int v) { return sqlite3_bind_int(stmt_, i, v); }
  40.     int bind(int i, string v) {
  41.         sqlite3_bind_text(stmt_, i, v.c_str(), v.length(), 0);
  42.     }
  43.     int reset() { sqlite3_reset(stmt_); }
  44. private:
  45.     int prepare() {
  46.         return sqlite3_prepare_v2(db_, sql_.c_str(), sql_.length(), &stmt_, 0);
  47.     }
  48.     sqlite3* db_;
  49.     string sql_;
  50.     sqlite3_stmt* stmt_;
  51. };
  52.  
  53. int get_row_count(connection& conn) {
  54.     statement select(conn, "SELECT count(id) FROM test;");
  55.     if (SQLITE_ROW == select.step())
  56.         return select.column_int(0);
  57.     return 0;
  58. }
  59.  
  60. int insert_random(sqlite3* db, string dbpath, int tno) {
  61.     statement insert(db, "INSERT INTO test (n,name) VALUES (?,?);");
  62.     string name = "Thread " + std::to_string(tno);
  63.     for (int i=0; i<ROWS_PER_THREAD; ++i) {
  64.         insert.reset();
  65.         insert.bind(1, rand());
  66.         insert.bind(2, name);
  67.         if (insert.step() != SQLITE_DONE) {
  68.             cerr << name << ": " << sqlite3_errmsg(db) << endl;
  69.             break;
  70.         }
  71.     }
  72. }
  73.  
  74. int new_connection_insert_random(sqlite3* db, string dbpath, int tno) {
  75.     connection conn(dbpath);
  76.     return insert_random(conn, dbpath, tno);
  77. }
  78.  
  79. template<class Function>
  80. bool run(Function&& func, string dbpath) {
  81.     connection conn(dbpath);
  82.     conn.exec("DROP TABLE IF EXISTS test;");
  83.     conn.exec("CREATE TABLE test ("
  84.               "   id   INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
  85.               "   n    INTEGER,"
  86.               "   name TEXT );");
  87.  
  88.     std::vector<std::thread> threads;
  89.     for (int i=1; i<=NUM_THREADS; ++i)
  90.         threads.emplace_back(func, conn, dbpath, i);
  91.     for (auto t=threads.begin(); t!=threads.end(); ++t) t->join();
  92.     return (get_row_count(conn) == ROWS_PER_THREAD*NUM_THREADS);
  93. }
  94.  
  95. int main() {
  96.     TEST(run(insert_random, "/var/tmp/testdb1.db"));
  97.     TEST(run(new_connection_insert_random, "/var/tmp/testdb2.db"));
  98. }
RAW Paste Data
Top