/databases/sqlite.go

https://github.com/sj14/dbbench · Go · 105 lines · 76 code · 14 blank · 15 comment · 24 complexity · 1633bf1f597cd62fa4e9d83a6e83ad20 MD5 · raw file

  1. package databases
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "log"
  6. "os"
  7. "github.com/sj14/dbbench/benchmark"
  8. )
  9. // SQLite implements the bencher interface.
  10. type SQLite struct {
  11. db *sql.DB
  12. }
  13. var (
  14. dbPath string
  15. dbCreated bool // DB file was created by dbbench
  16. )
  17. // NewSQLite retruns a new SQLite bencher.
  18. func NewSQLite(path string) *SQLite {
  19. dbPath = path
  20. if _, err := os.Stat(path); os.IsNotExist(err) {
  21. // We will create the database file.
  22. dbCreated = true
  23. }
  24. // Automatically creates the DB file if it doesn't exist yet.
  25. db, err := sql.Open("sqlite3", fmt.Sprintf("%s?cache=shared", path))
  26. if err != nil {
  27. log.Fatalf("failed to open connection: %v\n", err)
  28. }
  29. db.SetMaxOpenConns(1)
  30. p := &SQLite{db: db}
  31. return p
  32. }
  33. // Benchmarks returns the individual benchmark statements for sqlite.
  34. func (m *SQLite) Benchmarks() []benchmark.Benchmark {
  35. return []benchmark.Benchmark{
  36. {Name: "inserts", Type: benchmark.TypeLoop, Stmt: "INSERT INTO dbbench_simple (id, balance) VALUES( {{.Iter}}, {{call .RandInt63}});"},
  37. {Name: "selects", Type: benchmark.TypeLoop, Stmt: "SELECT * FROM dbbench_simple WHERE id = {{.Iter}};"},
  38. {Name: "updates", Type: benchmark.TypeLoop, Stmt: "UPDATE dbbench_simple SET balance = {{call .RandInt63}} WHERE id = {{.Iter}};"},
  39. {Name: "deletes", Type: benchmark.TypeLoop, Stmt: "DELETE FROM dbbench_simple WHERE id = {{.Iter}};"},
  40. // {"relation_insert0", benchmark.TypeLoop, "INSERT INTO dbbench_relational_one (oid, balance_one) VALUES( {{.Iter}}, {{call .RandInt63}});"},
  41. // {"relation_insert1", benchmark.TypeLoop, "INSERT INTO dbbench_relational_two (relation, balance_two) VALUES( {{.Iter}}, {{call .RandInt63}});"},
  42. // {"relation_select", benchmark.TypeLoop, "SELECT * FROM dbbench_relational_two INNER JOIN dbbench_relational_one ON dbbench_relational_one.oid = relation WHERE relation = {{.Iter}};"},
  43. // {"relation_delete1", benchmark.TypeLoop, "DELETE FROM dbbench_relational_two WHERE relation = {{.Iter}};"},
  44. // {"relation_delete0", benchmark.TypeLoop, "DELETE FROM dbbench_relational_one WHERE oid = {{.Iter}};"},
  45. }
  46. }
  47. // Setup initializes the database for the benchmark.
  48. func (m *SQLite) Setup() {
  49. if _, err := m.db.Exec("CREATE TABLE IF NOT EXISTS dbbench_simple (id INT PRIMARY KEY, balance DECIMAL);"); err != nil {
  50. log.Fatalf("failed to create table dbbench_simple: %v\n", err)
  51. }
  52. if _, err := m.db.Exec("CREATE TABLE IF NOT EXISTS dbbench_relational_one (oid INT PRIMARY KEY, balance_one DECIMAL);"); err != nil {
  53. log.Fatalf("failed to create table dbbench_relational_one: %v\n", err)
  54. }
  55. if _, err := m.db.Exec("CREATE TABLE IF NOT EXISTS dbbench_relational_two (balance_two DECIMAL, relation INT PRIMARY KEY, FOREIGN KEY(relation) REFERENCES dbbench_relational_one(oid));"); err != nil {
  56. log.Fatalf("failed to create table dbbench_relational_two: %v\n", err)
  57. }
  58. if _, err := m.db.Exec("PRAGMA foreign_keys = ON;"); err != nil {
  59. log.Fatalf("failed to enabled foreign keys: %v\n", err)
  60. }
  61. }
  62. // Cleanup removes all remaining benchmarking data.
  63. func (m *SQLite) Cleanup() {
  64. if _, err := m.db.Exec("DROP TABLE dbbench_simple"); err != nil {
  65. log.Printf("failed to drop table: %v\n", err)
  66. }
  67. if _, err := m.db.Exec("DROP TABLE dbbench_relational_two"); err != nil {
  68. log.Printf("failed to drop table: %v\n", err)
  69. }
  70. if _, err := m.db.Exec("DROP TABLE dbbench_relational_one"); err != nil {
  71. log.Printf("failed to drop table: %v\n", err)
  72. }
  73. if err := m.db.Close(); err != nil {
  74. log.Printf("failed to close connection: %v", err)
  75. }
  76. // The DB file existed before, don't remove it.
  77. if !dbCreated {
  78. return
  79. }
  80. if err := os.Remove(dbPath); err != nil {
  81. log.Printf("not able to delete created database file: %v\n", err)
  82. }
  83. }
  84. // Exec executes the given statement on the database.
  85. func (m *SQLite) Exec(stmt string) {
  86. // driver has no support for results
  87. _, err := m.db.Exec(stmt)
  88. if err != nil {
  89. log.Printf("%v failed: %v", stmt, err)
  90. }
  91. }