/sqlite/sqlite.go

https://github.com/status-im/status-go · Go · 88 lines · 59 code · 14 blank · 15 comment · 20 complexity · 91d9eddba5953d4aee32d3ac0911fe62 MD5 · raw file

  1. package sqlite
  2. import (
  3. "database/sql"
  4. "errors"
  5. "fmt"
  6. _ "github.com/mutecomm/go-sqlcipher" // We require go sqlcipher that overrides default implementation
  7. )
  8. const (
  9. // The reduced number of kdf iterations (for performance reasons) which is
  10. // currently used for derivation of the database key
  11. // https://github.com/status-im/status-go/pull/1343
  12. // https://notes.status.im/i8Y_l7ccTiOYq09HVgoFwA
  13. kdfIterationsNumber = 3200
  14. // WALMode for sqlite.
  15. WALMode = "wal"
  16. )
  17. func openDB(path, key string) (*sql.DB, error) {
  18. db, err := sql.Open("sqlite3", path)
  19. if err != nil {
  20. return nil, err
  21. }
  22. // Disable concurrent access as not supported by the driver
  23. db.SetMaxOpenConns(1)
  24. if _, err = db.Exec("PRAGMA foreign_keys=ON"); err != nil {
  25. return nil, err
  26. }
  27. keyString := fmt.Sprintf("PRAGMA key = '%s'", key)
  28. if _, err = db.Exec(keyString); err != nil {
  29. return nil, errors.New("failed to set key pragma")
  30. }
  31. if _, err = db.Exec(fmt.Sprintf("PRAGMA kdf_iter = '%d'", kdfIterationsNumber)); err != nil {
  32. return nil, err
  33. }
  34. // readers do not block writers and faster i/o operations
  35. // https://www.sqlite.org/draft/wal.html
  36. // must be set after db is encrypted
  37. var mode string
  38. err = db.QueryRow("PRAGMA journal_mode=WAL").Scan(&mode)
  39. if err != nil {
  40. return nil, err
  41. }
  42. if mode != WALMode {
  43. return nil, fmt.Errorf("unable to set journal_mode to WAL. actual mode %s", mode)
  44. }
  45. return db, nil
  46. }
  47. // OpenDB opens not-encrypted database.
  48. func OpenDB(path, key string) (*sql.DB, error) {
  49. return openDB(path, key)
  50. }
  51. // OpenUnecryptedDB opens database with setting PRAGMA key.
  52. func OpenUnecryptedDB(path string) (*sql.DB, error) {
  53. db, err := sql.Open("sqlite3", path)
  54. if err != nil {
  55. return nil, err
  56. }
  57. // Disable concurrent access as not supported by the driver
  58. db.SetMaxOpenConns(1)
  59. if _, err = db.Exec("PRAGMA foreign_keys=ON"); err != nil {
  60. return nil, err
  61. }
  62. // readers do not block writers and faster i/o operations
  63. // https://www.sqlite.org/draft/wal.html
  64. // must be set after db is encrypted
  65. var mode string
  66. err = db.QueryRow("PRAGMA journal_mode=WAL").Scan(&mode)
  67. if err != nil {
  68. return nil, err
  69. }
  70. if mode != WALMode {
  71. return nil, fmt.Errorf("unable to set journal_mode to WAL. actual mode %s", mode)
  72. }
  73. return db, nil
  74. }