status-go/appdatabase/database.go

110 lines
3.1 KiB
Go
Raw Normal View History

2019-07-25 05:35:09 +00:00
package appdatabase
import (
"database/sql"
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
"errors"
"github.com/ethereum/go-ethereum/log"
2019-07-25 05:35:09 +00:00
"github.com/status-im/status-go/appdatabase/migrations"
migrationsprevnodecfg "github.com/status-im/status-go/appdatabase/migrationsprevnodecfg"
"github.com/status-im/status-go/nodecfg"
2019-07-25 05:35:09 +00:00
"github.com/status-im/status-go/sqlite"
)
const nodeCfgMigrationDate = 1640111208
2019-07-25 05:35:09 +00:00
// InitializeDB creates db file at a given path and applies migrations.
func InitializeDB(path, password string, kdfIterationsNumber int) (*sql.DB, error) {
db, err := sqlite.OpenDB(path, password, kdfIterationsNumber)
2019-07-25 05:35:09 +00:00
if err != nil {
return nil, err
}
// Check if the migration table exists
row := db.QueryRow("SELECT exists(SELECT name FROM sqlite_master WHERE type='table' AND name='status_go_schema_migrations')")
migrationTableExists := false
err = row.Scan(&migrationTableExists)
if err != nil && err != sql.ErrNoRows {
return nil, err
}
var lastMigration uint64 = 0
if migrationTableExists {
row = db.QueryRow("SELECT version FROM status_go_schema_migrations")
err = row.Scan(&lastMigration)
if err != nil && err != sql.ErrNoRows {
return nil, err
}
}
if !migrationTableExists || (lastMigration > 0 && lastMigration < nodeCfgMigrationDate) {
// If it's the first time migration's being run, or latest migration happened before migrating the nodecfg table
err = migrationsprevnodecfg.Migrate(db)
if err != nil {
return nil, err
}
// NodeConfig migration cannot be done with SQL
err = nodecfg.MigrateNodeConfig(db)
if err != nil {
return nil, err
}
}
2019-07-25 05:35:09 +00:00
err = migrations.Migrate(db)
if err != nil {
return nil, err
}
return db, nil
}
2021-01-07 11:15:02 +00:00
// DecryptDatabase creates an unencrypted copy of the database and copies it
// over to the given directory
func DecryptDatabase(oldPath, newPath, password string, kdfIterationsNumber int) error {
return sqlite.DecryptDB(oldPath, newPath, password, kdfIterationsNumber)
2021-01-07 11:15:02 +00:00
}
// EncryptDatabase creates an encrypted copy of the database and copies it to the
// user path
func EncryptDatabase(oldPath, newPath, password string, kdfIterationsNumber int) error {
return sqlite.EncryptDB(oldPath, newPath, password, kdfIterationsNumber)
2021-01-07 11:15:02 +00:00
}
func ChangeDatabasePassword(path string, password string, kdfIterationsNumber int, newPassword string) error {
return sqlite.ChangeEncryptionKey(path, password, kdfIterationsNumber, newPassword)
}
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
// GetDBFilename takes an instance of sql.DB and returns the filename of the "main" database
func GetDBFilename(db *sql.DB) (string, error) {
if db == nil {
logger := log.New()
logger.Warn("GetDBFilename was passed a nil pointer sql.DB")
return "", nil
}
var i, category, filename string
rows, err := db.Query("PRAGMA database_list;")
if err != nil {
return "", err
}
defer rows.Close()
for rows.Next() {
err = rows.Scan(&i, &category, &filename)
if err != nil {
return "", err
}
// The "main" database is the one we care about
if category == "main" {
return filename, nil
}
}
if err := rows.Err(); err != nil {
return "", err
}
return "", errors.New("no main database found")
}