diff --git a/context.go b/context.go index 6d32797..cb16eb3 100644 --- a/context.go +++ b/context.go @@ -165,7 +165,7 @@ func New(world_dir string) (*Context, error) { ctx.mod_storage_db, err = connectAndMigrate( dbtype, path.Join(world_dir, "mod_storage.sqlite"), - "not implemented", + wc[worldconfig.CONFIG_PSQL_MOD_STORAGE_CONNECTION], mod_storage.MigrateModStorageDB, ) if err != nil { diff --git a/mod_storage/mod_storage_migrate.go b/mod_storage/migrate.go similarity index 66% rename from mod_storage/mod_storage_migrate.go rename to mod_storage/migrate.go index 41690d4..ae782a5 100644 --- a/mod_storage/mod_storage_migrate.go +++ b/mod_storage/migrate.go @@ -17,6 +17,14 @@ func MigrateModStorageDB(db *sql.DB, dbtype types.DatabaseType) error { value BLOB NOT NULL, PRIMARY KEY (modname, key) )`) + case types.DATABASE_POSTGRES: + _, err = db.Exec(` + CREATE TABLE IF NOT EXISTS mod_storage ( + modname TEXT NOT NULL, + key BYTEA NOT NULL, + value BYTEA NOT NULL, + PRIMARY KEY (modname, key) + )`) } return err } diff --git a/mod_storage/mod_storage_migrate_test.go b/mod_storage/migrate_test.go similarity index 100% rename from mod_storage/mod_storage_migrate_test.go rename to mod_storage/migrate_test.go diff --git a/mod_storage/mod_storage.go b/mod_storage/mod_storage.go index c75154e..2a6b4f0 100644 --- a/mod_storage/mod_storage.go +++ b/mod_storage/mod_storage.go @@ -28,6 +28,8 @@ func NewModStorageRepository(db *sql.DB, dbtype types.DatabaseType) ModStorageRe switch dbtype { case types.DATABASE_SQLITE: return &modStorageSqliteRepository{db: db} + case types.DATABASE_POSTGRES: + return &modStoragePostgresRepository{db: db} default: return nil } diff --git a/mod_storage/postgres.go b/mod_storage/postgres.go new file mode 100644 index 0000000..1d339bb --- /dev/null +++ b/mod_storage/postgres.go @@ -0,0 +1,99 @@ +package mod_storage + +import ( + "archive/zip" + "bufio" + "bytes" + "database/sql" + "encoding/json" +) + +type modStoragePostgresRepository struct { + db *sql.DB +} + +func (repo *modStoragePostgresRepository) Get(modname string, key []byte) (*ModStorageEntry, error) { + row := repo.db.QueryRow("select modname,key,value from entries where modname = $1 and key = $2", modname, key) + entry := &ModStorageEntry{} + err := row.Scan(&entry.ModName, &entry.Key, &entry.Value) + if err == sql.ErrNoRows { + return nil, nil + } + return entry, err +} + +func (repo *modStoragePostgresRepository) Create(entry *ModStorageEntry) error { + _, err := repo.db.Exec("insert into entries(modname,key,value) values($1,$2,$3)", entry.ModName, entry.Key, entry.Value) + return err +} + +func (repo *modStoragePostgresRepository) Update(entry *ModStorageEntry) error { + _, err := repo.db.Exec("update entries set value = $1 where modname = $2 and key = $3", entry.Value, entry.ModName, entry.Key) + return err +} + +func (repo *modStoragePostgresRepository) Delete(modname string, key []byte) error { + _, err := repo.db.Exec("delete from entries where modname = $1 and key = $2", modname, key) + return err +} + +func (repo *modStoragePostgresRepository) Count() (int64, error) { + row := repo.db.QueryRow("select count(*) from entries") + count := int64(0) + err := row.Scan(&count) + return count, err +} + +func (repo *modStoragePostgresRepository) Export(z *zip.Writer) error { + w, err := z.Create("mod_storage.json") + if err != nil { + return err + } + enc := json.NewEncoder(w) + + rows, err := repo.db.Query("select modname,key,value from entries") + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + e := &ModStorageEntry{} + err = rows.Scan(&e.ModName, &e.Key, &e.Value) + if err != nil { + return err + } + + err = enc.Encode(e) + if err != nil { + return err + } + } + + return nil +} + +func (repo *modStoragePostgresRepository) Import(z *zip.Reader) error { + f, err := z.Open("mod_storage.json") + if err != nil { + return err + } + defer f.Close() + + sc := bufio.NewScanner(f) + for sc.Scan() { + dc := json.NewDecoder(bytes.NewReader(sc.Bytes())) + e := &ModStorageEntry{} + err = dc.Decode(e) + if err != nil { + return err + } + + _, err := repo.db.Exec("insert into entries(modname,key,value) values($1,$2,$3) on conflict set value = $3", e.ModName, e.Key, e.Value) + if err != nil { + return err + } + } + + return nil +} diff --git a/mod_storage/mod_storage_sqlite.go b/mod_storage/sqlite.go similarity index 100% rename from mod_storage/mod_storage_sqlite.go rename to mod_storage/sqlite.go diff --git a/mod_storage/mod_storage_sqlite_test.go b/mod_storage/sqlite_test.go similarity index 100% rename from mod_storage/mod_storage_sqlite_test.go rename to mod_storage/sqlite_test.go diff --git a/test-env.sh b/test-env.sh deleted file mode 100755 index f2750c0..0000000 --- a/test-env.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -export PGUSER=postgres -export PGPASSWORD=enter -export PGHOST=localhost -export PGDATABASE=postgres -export PGPORT=5432 diff --git a/worldconfig/parse.go b/worldconfig/parse.go index f51cc40..9b4b852 100644 --- a/worldconfig/parse.go +++ b/worldconfig/parse.go @@ -13,13 +13,14 @@ const ( ) const ( - CONFIG_PSQL_AUTH_CONNECTION = "pgsql_auth_connection" - CONFIG_AUTH_BACKEND = "auth_backend" - CONFIG_STORAGE_BACKEND = "mod_storage_backend" - CONFIG_PLAYER_BACKEND = "player_backend" - CONFIG_PSQL_PLAYER_CONNECTION = "pgsql_player_connection" - CONFIG_PSQL_MAP_CONNECTION = "pgsql_connection" - CONFIG_MAP_BACKEND = "backend" + CONFIG_MAP_BACKEND = "backend" + CONFIG_AUTH_BACKEND = "auth_backend" + CONFIG_STORAGE_BACKEND = "mod_storage_backend" + CONFIG_PLAYER_BACKEND = "player_backend" + CONFIG_PSQL_PLAYER_CONNECTION = "pgsql_player_connection" + CONFIG_PSQL_MAP_CONNECTION = "pgsql_connection" + CONFIG_PSQL_AUTH_CONNECTION = "pgsql_auth_connection" + CONFIG_PSQL_MOD_STORAGE_CONNECTION = "pgsql_mod_storage_connection" ) const DEFAULT_CONFIG = `