From ba7ec122f8692078afe1f4405436850b465dc922 Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Thu, 5 Mar 2026 23:05:55 +0100 Subject: [PATCH] revert: remove SQLite support An MMO server without multiplayer defeats the purpose. PostgreSQL is the right choice and Docker Compose already solves the setup pain. This reverts the common/db wrapper, SQLite schema, config Driver field, modernc.org/sqlite dependency, and all repo type changes while keeping the dashboard, wizard, and CI improvements from the previous commit. --- common/db/adapter.go | 68 -- common/db/adapter_test.go | 83 -- common/db/db.go | 149 --- config/config.go | 9 +- go.mod | 11 +- go.sum | 22 - main.go | 54 +- server/api/api_server.go | 11 +- server/api/repo_character.go | 6 +- server/api/repo_event.go | 6 +- server/api/repo_session.go | 6 +- server/api/repo_user.go | 6 +- server/channelserver/repo_achievement.go | 6 +- server/channelserver/repo_achievement_test.go | 3 +- server/channelserver/repo_cafe.go | 6 +- server/channelserver/repo_cafe_test.go | 3 +- server/channelserver/repo_character.go | 6 +- server/channelserver/repo_character_test.go | 3 +- server/channelserver/repo_distribution.go | 6 +- .../channelserver/repo_distribution_test.go | 3 +- server/channelserver/repo_diva.go | 6 +- server/channelserver/repo_diva_test.go | 3 +- server/channelserver/repo_event.go | 6 +- server/channelserver/repo_event_test.go | 3 +- server/channelserver/repo_festa.go | 6 +- server/channelserver/repo_festa_test.go | 3 +- server/channelserver/repo_gacha.go | 6 +- server/channelserver/repo_gacha_test.go | 3 +- server/channelserver/repo_goocoo.go | 6 +- server/channelserver/repo_goocoo_test.go | 3 +- server/channelserver/repo_guild.go | 6 +- server/channelserver/repo_guild_test.go | 5 +- server/channelserver/repo_house.go | 6 +- server/channelserver/repo_house_test.go | 3 +- server/channelserver/repo_mail.go | 6 +- server/channelserver/repo_mail_test.go | 3 +- server/channelserver/repo_mercenary.go | 6 +- server/channelserver/repo_mercenary_test.go | 3 +- server/channelserver/repo_misc.go | 6 +- server/channelserver/repo_misc_test.go | 3 +- server/channelserver/repo_rengoku.go | 6 +- server/channelserver/repo_rengoku_test.go | 3 +- server/channelserver/repo_scenario.go | 6 +- server/channelserver/repo_scenario_test.go | 3 +- server/channelserver/repo_session.go | 6 +- server/channelserver/repo_session_test.go | 3 +- server/channelserver/repo_shop.go | 6 +- server/channelserver/repo_shop_test.go | 3 +- server/channelserver/repo_stamp.go | 6 +- server/channelserver/repo_stamp_test.go | 3 +- server/channelserver/repo_tower.go | 6 +- server/channelserver/repo_tower_test.go | 3 +- server/channelserver/repo_user.go | 6 +- server/channelserver/repo_user_test.go | 3 +- .../session_lifecycle_integration_test.go | 26 +- server/channelserver/sys_channel_server.go | 44 +- server/channelserver/testhelpers_db.go | 44 +- server/migrations/migrations.go | 107 +-- server/migrations/migrations_test.go | 64 +- server/migrations/sqlite/0001_init.sql | 855 ------------------ .../sqlite/0002_catch_up_patches.sql | 3 - .../sqlite/0003_shop_items_bought_unique.sql | 2 - .../sqlite/0004_alliance_recruiting.sql | 2 - .../sqlite/0005_distribution_drop_data.sql | 2 - server/signserver/repo_character.go | 6 +- server/signserver/repo_session.go | 6 +- server/signserver/repo_user.go | 6 +- server/signserver/sign_server.go | 8 +- 68 files changed, 222 insertions(+), 1575 deletions(-) delete mode 100644 common/db/adapter.go delete mode 100644 common/db/adapter_test.go delete mode 100644 common/db/db.go delete mode 100644 server/migrations/sqlite/0001_init.sql delete mode 100644 server/migrations/sqlite/0002_catch_up_patches.sql delete mode 100644 server/migrations/sqlite/0003_shop_items_bought_unique.sql delete mode 100644 server/migrations/sqlite/0004_alliance_recruiting.sql delete mode 100644 server/migrations/sqlite/0005_distribution_drop_data.sql diff --git a/common/db/adapter.go b/common/db/adapter.go deleted file mode 100644 index de71b85bf..000000000 --- a/common/db/adapter.go +++ /dev/null @@ -1,68 +0,0 @@ -// Package db provides a database adapter that transparently translates -// PostgreSQL-style SQL to the active driver's dialect. -// -// When the driver is "sqlite", queries are rewritten on the fly: -// - $1, $2, ... → ?, ?, ... -// - now() → CURRENT_TIMESTAMP -// - ::type casts → removed -// - ILIKE → LIKE (SQLite LIKE is case-insensitive for ASCII) -package db - -import ( - "regexp" - "strings" - - "github.com/jmoiron/sqlx" -) - -// IsSQLite reports whether the given sqlx.DB is backed by a SQLite driver. -func IsSQLite(db *sqlx.DB) bool { - return db.DriverName() == "sqlite" || db.DriverName() == "sqlite3" -} - -// Adapt rewrites a PostgreSQL query for the active driver. -// For Postgres it's a no-op. For SQLite it translates placeholders and -// Postgres-specific syntax. -func Adapt(db *sqlx.DB, query string) string { - if !IsSQLite(db) { - return query - } - return AdaptSQL(query) -} - -// castRe matches Postgres type casts like ::int, ::text, ::timestamptz, -// ::character varying, etc. -// castRe matches Postgres type casts: ::int, ::text, ::timestamptz, -// ::character varying(N), etc. The space is allowed only when followed -// by a word char (e.g. "character varying") to avoid eating trailing spaces. -var castRe = regexp.MustCompile(`::[a-zA-Z_]\w*(?:\s+\w+)*(?:\([^)]*\))?`) - -// dollarParamRe matches Postgres-style positional parameters: $1, $2, etc. -var dollarParamRe = regexp.MustCompile(`\$\d+`) - -// AdaptSQL translates a PostgreSQL query to SQLite-compatible SQL. -// Exported so it can be tested without a real DB connection. -func AdaptSQL(query string) string { - // 1. Replace now() with CURRENT_TIMESTAMP - query = strings.ReplaceAll(query, "now()", "CURRENT_TIMESTAMP") - query = strings.ReplaceAll(query, "NOW()", "CURRENT_TIMESTAMP") - - // 2. Strip Postgres type casts (::int, ::text, ::timestamptz, etc.) - query = castRe.ReplaceAllString(query, "") - - // 3. ILIKE → LIKE (SQLite LIKE is case-insensitive for ASCII by default) - query = strings.ReplaceAll(query, " ILIKE ", " LIKE ") - query = strings.ReplaceAll(query, " ilike ", " LIKE ") - - // 4. Strip "public." schema prefix (SQLite has no schemas) - query = strings.ReplaceAll(query, "public.", "") - - // 5. TRUNCATE → DELETE FROM (SQLite has no TRUNCATE) - query = strings.ReplaceAll(query, "TRUNCATE ", "DELETE FROM ") - query = strings.ReplaceAll(query, "truncate ", "DELETE FROM ") - - // 6. Replace $1,$2,... → ?,?,... - query = dollarParamRe.ReplaceAllString(query, "?") - - return query -} diff --git a/common/db/adapter_test.go b/common/db/adapter_test.go deleted file mode 100644 index 08ff6f402..000000000 --- a/common/db/adapter_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package db - -import ( - "testing" -) - -func TestAdaptSQL(t *testing.T) { - tests := []struct { - name string - input string - want string - }{ - { - name: "placeholder rebind", - input: "SELECT * FROM users WHERE id=$1 AND name=$2", - want: "SELECT * FROM users WHERE id=? AND name=?", - }, - { - name: "now() replacement", - input: "UPDATE characters SET guild_post_checked=now() WHERE id=$1", - want: "UPDATE characters SET guild_post_checked=CURRENT_TIMESTAMP WHERE id=?", - }, - { - name: "type cast removal", - input: "UPDATE users SET frontier_points=frontier_points::int - $1 WHERE id=$2 RETURNING frontier_points", - want: "UPDATE users SET frontier_points=frontier_points - ? WHERE id=? RETURNING frontier_points", - }, - { - name: "text cast removal", - input: "SELECT COALESCE(friends, ''::text) FROM characters WHERE id=$1", - want: "SELECT COALESCE(friends, '') FROM characters WHERE id=?", - }, - { - name: "timestamptz cast removal", - input: "SELECT COALESCE(created_at, '2000-01-01'::timestamptz) FROM guilds WHERE id=$1", - want: "SELECT COALESCE(created_at, '2000-01-01') FROM guilds WHERE id=?", - }, - { - name: "ILIKE to LIKE", - input: "SELECT * FROM characters WHERE name ILIKE $1", - want: "SELECT * FROM characters WHERE name LIKE ?", - }, - { - name: "character varying cast", - input: "DEFAULT ''::character varying", - want: "DEFAULT ''", - }, - { - name: "no changes for standard SQL", - input: "SELECT COUNT(*) FROM users", - want: "SELECT COUNT(*) FROM users", - }, - { - name: "NOW uppercase", - input: "INSERT INTO events (start_time) VALUES (NOW())", - want: "INSERT INTO events (start_time) VALUES (CURRENT_TIMESTAMP)", - }, - { - name: "multi-digit params", - input: "INSERT INTO t (a,b,c) VALUES ($1,$2,$10)", - want: "INSERT INTO t (a,b,c) VALUES (?,?,?)", - }, - { - name: "public schema prefix", - input: "INSERT INTO public.distributions_accepted VALUES ($1, $2)", - want: "INSERT INTO distributions_accepted VALUES (?, ?)", - }, - { - name: "TRUNCATE to DELETE FROM", - input: "TRUNCATE public.cafebonus;", - want: "DELETE FROM cafebonus;", - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - got := AdaptSQL(tc.input) - if got != tc.want { - t.Errorf("\ngot: %s\nwant: %s", got, tc.want) - } - }) - } -} diff --git a/common/db/db.go b/common/db/db.go deleted file mode 100644 index 0a5171d30..000000000 --- a/common/db/db.go +++ /dev/null @@ -1,149 +0,0 @@ -// Package db provides a transparent database wrapper that rewrites -// PostgreSQL-style SQL for SQLite when needed. -package db - -import ( - "context" - "database/sql" - - "github.com/jmoiron/sqlx" -) - -// DB wraps *sqlx.DB and transparently adapts PostgreSQL queries for SQLite. -// For PostgreSQL, all methods are simple pass-throughs with zero overhead. -type DB struct { - *sqlx.DB - sqlite bool -} - -// Wrap creates a DB wrapper around an existing *sqlx.DB connection. -// Returns nil if db is nil. -func Wrap(db *sqlx.DB) *DB { - if db == nil { - return nil - } - return &DB{ - DB: db, - sqlite: IsSQLite(db), - } -} - -func (d *DB) adapt(query string) string { - if !d.sqlite { - return query - } - return AdaptSQL(query) -} - -// Exec executes a query without returning any rows. -func (d *DB) Exec(query string, args ...interface{}) (sql.Result, error) { - return d.DB.Exec(d.adapt(query), args...) -} - -// ExecContext executes a query without returning any rows. -func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { - return d.DB.ExecContext(ctx, d.adapt(query), args...) -} - -// Query executes a query that returns rows. -func (d *DB) Query(query string, args ...interface{}) (*sql.Rows, error) { - return d.DB.Query(d.adapt(query), args...) -} - -// QueryContext executes a query that returns rows. -func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) { - return d.DB.QueryContext(ctx, d.adapt(query), args...) -} - -// QueryRow executes a query that is expected to return at most one row. -func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { - return d.DB.QueryRow(d.adapt(query), args...) -} - -// QueryRowContext executes a query that is expected to return at most one row. -func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { - return d.DB.QueryRowContext(ctx, d.adapt(query), args...) -} - -// Get queries a single row and scans it into dest. -func (d *DB) Get(dest interface{}, query string, args ...interface{}) error { - return d.DB.Get(dest, d.adapt(query), args...) -} - -// Select queries multiple rows and scans them into dest. -func (d *DB) Select(dest interface{}, query string, args ...interface{}) error { - return d.DB.Select(dest, d.adapt(query), args...) -} - -// Queryx executes a query that returns sqlx.Rows. -func (d *DB) Queryx(query string, args ...interface{}) (*sqlx.Rows, error) { - return d.DB.Queryx(d.adapt(query), args...) -} - -// QueryRowx executes a query that returns a sqlx.Row. -func (d *DB) QueryRowx(query string, args ...interface{}) *sqlx.Row { - return d.DB.QueryRowx(d.adapt(query), args...) -} - -// QueryRowxContext executes a query that returns a sqlx.Row. -func (d *DB) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *sqlx.Row { - return d.DB.QueryRowxContext(ctx, d.adapt(query), args...) -} - -// BeginTxx starts a new transaction with context and options. -// The returned Tx wrapper adapts queries the same way as DB. -func (d *DB) BeginTxx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { - tx, err := d.DB.BeginTxx(ctx, opts) - if err != nil { - return nil, err - } - return &Tx{Tx: tx, sqlite: d.sqlite}, nil -} - -// Tx wraps *sqlx.Tx and transparently adapts PostgreSQL queries for SQLite. -type Tx struct { - *sqlx.Tx - sqlite bool -} - -func (t *Tx) adapt(query string) string { - if !t.sqlite { - return query - } - return AdaptSQL(query) -} - -// Exec executes a query without returning any rows. -func (t *Tx) Exec(query string, args ...interface{}) (sql.Result, error) { - return t.Tx.Exec(t.adapt(query), args...) -} - -// ExecContext executes a query without returning any rows. -func (t *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { - return t.Tx.ExecContext(ctx, t.adapt(query), args...) -} - -// Query executes a query that returns rows. -func (t *Tx) Query(query string, args ...interface{}) (*sql.Rows, error) { - return t.Tx.Query(t.adapt(query), args...) -} - -// QueryRow executes a query that is expected to return at most one row. -func (t *Tx) QueryRow(query string, args ...interface{}) *sql.Row { - return t.Tx.QueryRow(t.adapt(query), args...) -} - -// Queryx executes a query that returns sqlx.Rows. -func (t *Tx) Queryx(query string, args ...interface{}) (*sqlx.Rows, error) { - return t.Tx.Queryx(t.adapt(query), args...) -} - -// QueryRowx executes a query that returns a sqlx.Row. -func (t *Tx) QueryRowx(query string, args ...interface{}) *sqlx.Row { - return t.Tx.QueryRowx(t.adapt(query), args...) -} - -// Get queries a single row and scans it into dest. -func (t *Tx) Get(dest interface{}, query string, args ...interface{}) error { - return t.Tx.Get(dest, t.adapt(query), args...) -} diff --git a/config/config.go b/config/config.go index 1c558d06c..8555fe701 100644 --- a/config/config.go +++ b/config/config.go @@ -231,12 +231,8 @@ type Course struct { Enabled bool } -// Database holds the database config. -// Driver can be "postgres" (default) or "sqlite". -// When Driver is "sqlite", only Database (file path) is used; -// Host, Port, User, and Password are ignored. +// Database holds the postgres database config. type Database struct { - Driver string // "postgres" or "sqlite" Host string Port int User string @@ -458,8 +454,7 @@ func registerDefaults() { {Name: "EXRenewing", Enabled: true}, }) - // Database (Password deliberately has no default for postgres) - viper.SetDefault("Database.Driver", "postgres") + // Database (Password deliberately has no default) viper.SetDefault("Database.Host", "localhost") viper.SetDefault("Database.Port", 5432) viper.SetDefault("Database.User", "postgres") diff --git a/go.mod b/go.mod index 23fa722e1..b7b834a12 100644 --- a/go.mod +++ b/go.mod @@ -16,18 +16,13 @@ require ( require ( github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/ncruces/go-strftime v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -36,13 +31,9 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/net v0.49.0 // indirect golang.org/x/sys v0.41.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.67.6 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.46.1 // indirect ) diff --git a/go.sum b/go.sum index c58be6bb9..576eb28df 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -111,7 +109,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -127,8 +124,6 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -164,14 +159,10 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= -github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -180,8 +171,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -248,8 +237,6 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -361,7 +348,6 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -535,14 +521,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= -modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= -modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index 8f764f6a3..edee6de24 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,6 @@ import ( "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "go.uber.org/zap" - _ "modernc.org/sqlite" ) // Temporary DB auto clean on startup for quick development & testing. @@ -109,7 +108,7 @@ func main() { logger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit())) logger.Info(fmt.Sprintf("Client Mode: %s (%d)", config.ClientMode, config.RealClientMode)) - if config.Database.Driver != "sqlite" && config.Database.Password == "" { + if config.Database.Password == "" { preventClose(config, "Database password is blank") } @@ -137,38 +136,19 @@ func main() { logger.Info("Discord: Disabled") } - // Create the DB pool. - var db *sqlx.DB - if config.Database.Driver == "sqlite" { - dbPath := config.Database.Database - if dbPath == "" || dbPath == "erupe" { - dbPath = "erupe.db" - } - db, err = sqlx.Open("sqlite", dbPath+"?_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)") - if err != nil { - preventClose(config, fmt.Sprintf("Database: Failed to open SQLite %s, %s", dbPath, err.Error())) - } - // SQLite only supports one writer at a time. - db.SetMaxOpenConns(1) - logger.Info(fmt.Sprintf("Database: SQLite opened (%s)", dbPath)) - } else { - connectString := fmt.Sprintf( - "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", - config.Database.Host, - config.Database.Port, - config.Database.User, - config.Database.Password, - config.Database.Database, - ) - db, err = sqlx.Open("postgres", connectString) - if err != nil { - preventClose(config, fmt.Sprintf("Database: Failed to open, %s", err.Error())) - } - // Configure connection pool to avoid exhausting PostgreSQL under load. - db.SetMaxOpenConns(50) - db.SetMaxIdleConns(10) - db.SetConnMaxLifetime(5 * time.Minute) - db.SetConnMaxIdleTime(2 * time.Minute) + // Create the postgres DB pool. + connectString := fmt.Sprintf( + "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", + config.Database.Host, + config.Database.Port, + config.Database.User, + config.Database.Password, + config.Database.Database, + ) + + db, err := sqlx.Open("postgres", connectString) + if err != nil { + preventClose(config, fmt.Sprintf("Database: Failed to open, %s", err.Error())) } // Test the DB connection. @@ -177,6 +157,12 @@ func main() { preventClose(config, fmt.Sprintf("Database: Failed to ping, %s", err.Error())) } + // Configure connection pool to avoid exhausting PostgreSQL under load. + db.SetMaxOpenConns(50) + db.SetMaxIdleConns(10) + db.SetConnMaxLifetime(5 * time.Minute) + db.SetConnMaxIdleTime(2 * time.Minute) + logger.Info("Database: Started successfully") // Run database migrations diff --git a/server/api/api_server.go b/server/api/api_server.go index 13a3297cf..557d4611d 100644 --- a/server/api/api_server.go +++ b/server/api/api_server.go @@ -9,8 +9,6 @@ import ( "sync" "time" - dbutil "erupe-ce/common/db" - "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/jmoiron/sqlx" @@ -48,11 +46,10 @@ func NewAPIServer(config *Config) *APIServer { httpServer: &http.Server{}, } if config.DB != nil { - wdb := dbutil.Wrap(config.DB) - s.userRepo = NewAPIUserRepository(wdb) - s.charRepo = NewAPICharacterRepository(wdb) - s.sessionRepo = NewAPISessionRepository(wdb) - s.eventRepo = NewAPIEventRepository(wdb) + s.userRepo = NewAPIUserRepository(config.DB) + s.charRepo = NewAPICharacterRepository(config.DB) + s.sessionRepo = NewAPISessionRepository(config.DB) + s.eventRepo = NewAPIEventRepository(config.DB) } return s } diff --git a/server/api/repo_character.go b/server/api/repo_character.go index 7d3ffa3f6..6bddc5815 100644 --- a/server/api/repo_character.go +++ b/server/api/repo_character.go @@ -3,16 +3,16 @@ package api import ( "context" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // APICharacterRepository implements APICharacterRepo with PostgreSQL. type APICharacterRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewAPICharacterRepository creates a new APICharacterRepository. -func NewAPICharacterRepository(db *dbutil.DB) *APICharacterRepository { +func NewAPICharacterRepository(db *sqlx.DB) *APICharacterRepository { return &APICharacterRepository{db: db} } diff --git a/server/api/repo_event.go b/server/api/repo_event.go index 40694fb66..c6a2cef2c 100644 --- a/server/api/repo_event.go +++ b/server/api/repo_event.go @@ -6,15 +6,15 @@ import ( "errors" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) type apiEventRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewAPIEventRepository creates an APIEventRepo backed by PostgreSQL. -func NewAPIEventRepository(db *dbutil.DB) APIEventRepo { +func NewAPIEventRepository(db *sqlx.DB) APIEventRepo { return &apiEventRepository{db: db} } diff --git a/server/api/repo_session.go b/server/api/repo_session.go index dffc3fa25..80a842d00 100644 --- a/server/api/repo_session.go +++ b/server/api/repo_session.go @@ -3,16 +3,16 @@ package api import ( "context" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // APISessionRepository implements APISessionRepo with PostgreSQL. type APISessionRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewAPISessionRepository creates a new APISessionRepository. -func NewAPISessionRepository(db *dbutil.DB) *APISessionRepository { +func NewAPISessionRepository(db *sqlx.DB) *APISessionRepository { return &APISessionRepository{db: db} } diff --git a/server/api/repo_user.go b/server/api/repo_user.go index 37af109b1..dfb25664f 100644 --- a/server/api/repo_user.go +++ b/server/api/repo_user.go @@ -4,16 +4,16 @@ import ( "context" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // APIUserRepository implements APIUserRepo with PostgreSQL. type APIUserRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewAPIUserRepository creates a new APIUserRepository. -func NewAPIUserRepository(db *dbutil.DB) *APIUserRepository { +func NewAPIUserRepository(db *sqlx.DB) *APIUserRepository { return &APIUserRepository{db: db} } diff --git a/server/channelserver/repo_achievement.go b/server/channelserver/repo_achievement.go index 578fdbcee..26e12dd79 100644 --- a/server/channelserver/repo_achievement.go +++ b/server/channelserver/repo_achievement.go @@ -3,16 +3,16 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // AchievementRepository centralizes all database access for the achievements table. type AchievementRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewAchievementRepository creates a new AchievementRepository. -func NewAchievementRepository(db *dbutil.DB) *AchievementRepository { +func NewAchievementRepository(db *sqlx.DB) *AchievementRepository { return &AchievementRepository{db: db} } diff --git a/server/channelserver/repo_achievement_test.go b/server/channelserver/repo_achievement_test.go index 371ba3d94..ae9a08cc8 100644 --- a/server/channelserver/repo_achievement_test.go +++ b/server/channelserver/repo_achievement_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -12,7 +11,7 @@ func setupAchievementRepo(t *testing.T) (*AchievementRepository, *sqlx.DB, uint3 db := SetupTestDB(t) userID := CreateTestUser(t, db, "ach_test_user") charID := CreateTestCharacter(t, db, userID, "AchChar") - repo := NewAchievementRepository(dbutil.Wrap(db)) + repo := NewAchievementRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_cafe.go b/server/channelserver/repo_cafe.go index 7781f7192..064ef4ffe 100644 --- a/server/channelserver/repo_cafe.go +++ b/server/channelserver/repo_cafe.go @@ -1,16 +1,16 @@ package channelserver import ( - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // CafeRepository centralizes all database access for cafe-related tables. type CafeRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewCafeRepository creates a new CafeRepository. -func NewCafeRepository(db *dbutil.DB) *CafeRepository { +func NewCafeRepository(db *sqlx.DB) *CafeRepository { return &CafeRepository{db: db} } diff --git a/server/channelserver/repo_cafe_test.go b/server/channelserver/repo_cafe_test.go index 5601ece73..e1c43e98a 100644 --- a/server/channelserver/repo_cafe_test.go +++ b/server/channelserver/repo_cafe_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -12,7 +11,7 @@ func setupCafeRepo(t *testing.T) (*CafeRepository, *sqlx.DB, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "cafe_test_user") charID := CreateTestCharacter(t, db, userID, "CafeChar") - repo := NewCafeRepository(dbutil.Wrap(db)) + repo := NewCafeRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_character.go b/server/channelserver/repo_character.go index 6a72baf9a..89028c6c8 100644 --- a/server/channelserver/repo_character.go +++ b/server/channelserver/repo_character.go @@ -4,16 +4,16 @@ import ( "database/sql" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // CharacterRepository centralizes all database access for the characters table. type CharacterRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewCharacterRepository creates a new CharacterRepository. -func NewCharacterRepository(db *dbutil.DB) *CharacterRepository { +func NewCharacterRepository(db *sqlx.DB) *CharacterRepository { return &CharacterRepository{db: db} } diff --git a/server/channelserver/repo_character_test.go b/server/channelserver/repo_character_test.go index 945bb4967..52ebdd780 100644 --- a/server/channelserver/repo_character_test.go +++ b/server/channelserver/repo_character_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "time" @@ -13,7 +12,7 @@ func setupCharRepo(t *testing.T) (*CharacterRepository, *sqlx.DB, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "repo_test_user") charID := CreateTestCharacter(t, db, userID, "RepoChar") - repo := NewCharacterRepository(dbutil.Wrap(db)) + repo := NewCharacterRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_distribution.go b/server/channelserver/repo_distribution.go index d4193956d..7ef8a42f6 100644 --- a/server/channelserver/repo_distribution.go +++ b/server/channelserver/repo_distribution.go @@ -1,17 +1,17 @@ package channelserver import ( - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // DistributionRepository centralizes all database access for the distribution, // distribution_items, and distributions_accepted tables. type DistributionRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewDistributionRepository creates a new DistributionRepository. -func NewDistributionRepository(db *dbutil.DB) *DistributionRepository { +func NewDistributionRepository(db *sqlx.DB) *DistributionRepository { return &DistributionRepository{db: db} } diff --git a/server/channelserver/repo_distribution_test.go b/server/channelserver/repo_distribution_test.go index fae6f556b..fc2286142 100644 --- a/server/channelserver/repo_distribution_test.go +++ b/server/channelserver/repo_distribution_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -12,7 +11,7 @@ func setupDistributionRepo(t *testing.T) (*DistributionRepository, *sqlx.DB, uin db := SetupTestDB(t) userID := CreateTestUser(t, db, "dist_test_user") charID := CreateTestCharacter(t, db, userID, "DistChar") - repo := NewDistributionRepository(dbutil.Wrap(db)) + repo := NewDistributionRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_diva.go b/server/channelserver/repo_diva.go index 4cd16ee49..90b53e201 100644 --- a/server/channelserver/repo_diva.go +++ b/server/channelserver/repo_diva.go @@ -1,16 +1,16 @@ package channelserver import ( - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // DivaRepository centralizes all database access for diva defense events. type DivaRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewDivaRepository creates a new DivaRepository. -func NewDivaRepository(db *dbutil.DB) *DivaRepository { +func NewDivaRepository(db *sqlx.DB) *DivaRepository { return &DivaRepository{db: db} } diff --git a/server/channelserver/repo_diva_test.go b/server/channelserver/repo_diva_test.go index b7b623657..bd6ab0d60 100644 --- a/server/channelserver/repo_diva_test.go +++ b/server/channelserver/repo_diva_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -10,7 +9,7 @@ import ( func setupDivaRepo(t *testing.T) (*DivaRepository, *sqlx.DB) { t.Helper() db := SetupTestDB(t) - repo := NewDivaRepository(dbutil.Wrap(db)) + repo := NewDivaRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db } diff --git a/server/channelserver/repo_event.go b/server/channelserver/repo_event.go index 649a4ea5e..eaae596e7 100644 --- a/server/channelserver/repo_event.go +++ b/server/channelserver/repo_event.go @@ -4,7 +4,7 @@ import ( "context" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // EventQuest represents a row from the event_quests table. @@ -22,11 +22,11 @@ type EventQuest struct { // EventRepository centralizes all database access for event-related tables. type EventRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewEventRepository creates a new EventRepository. -func NewEventRepository(db *dbutil.DB) *EventRepository { +func NewEventRepository(db *sqlx.DB) *EventRepository { return &EventRepository{db: db} } diff --git a/server/channelserver/repo_event_test.go b/server/channelserver/repo_event_test.go index 5ad3d6f06..36ad33b56 100644 --- a/server/channelserver/repo_event_test.go +++ b/server/channelserver/repo_event_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "time" @@ -11,7 +10,7 @@ import ( func setupEventRepo(t *testing.T) (*EventRepository, *sqlx.DB) { t.Helper() db := SetupTestDB(t) - repo := NewEventRepository(dbutil.Wrap(db)) + repo := NewEventRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db } diff --git a/server/channelserver/repo_festa.go b/server/channelserver/repo_festa.go index bc694658d..dbac352dd 100644 --- a/server/channelserver/repo_festa.go +++ b/server/channelserver/repo_festa.go @@ -4,17 +4,17 @@ import ( "context" "database/sql" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // FestaRepository centralizes all database access for festa-related tables // (events, festa_registrations, festa_submissions, festa_prizes, festa_prizes_accepted, festa_trials, guild_characters). type FestaRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewFestaRepository creates a new FestaRepository. -func NewFestaRepository(db *dbutil.DB) *FestaRepository { +func NewFestaRepository(db *sqlx.DB) *FestaRepository { return &FestaRepository{db: db} } diff --git a/server/channelserver/repo_festa_test.go b/server/channelserver/repo_festa_test.go index f94f137f2..0ef98bb77 100644 --- a/server/channelserver/repo_festa_test.go +++ b/server/channelserver/repo_festa_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "time" @@ -14,7 +13,7 @@ func setupFestaRepo(t *testing.T) (*FestaRepository, *sqlx.DB, uint32, uint32) { userID := CreateTestUser(t, db, "festa_test_user") charID := CreateTestCharacter(t, db, userID, "FestaChar") guildID := CreateTestGuild(t, db, charID, "FestaGuild") - repo := NewFestaRepository(dbutil.Wrap(db)) + repo := NewFestaRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID, guildID } diff --git a/server/channelserver/repo_gacha.go b/server/channelserver/repo_gacha.go index 8a6011660..b2efcf303 100644 --- a/server/channelserver/repo_gacha.go +++ b/server/channelserver/repo_gacha.go @@ -5,17 +5,17 @@ import ( "errors" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // GachaRepository centralizes all database access for gacha-related tables // (gacha_shop, gacha_entries, gacha_items, gacha_stepup, gacha_box). type GachaRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewGachaRepository creates a new GachaRepository. -func NewGachaRepository(db *dbutil.DB) *GachaRepository { +func NewGachaRepository(db *sqlx.DB) *GachaRepository { return &GachaRepository{db: db} } diff --git a/server/channelserver/repo_gacha_test.go b/server/channelserver/repo_gacha_test.go index 6b4d63683..64f8c4a71 100644 --- a/server/channelserver/repo_gacha_test.go +++ b/server/channelserver/repo_gacha_test.go @@ -3,7 +3,6 @@ package channelserver import ( "database/sql" "errors" - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -14,7 +13,7 @@ func setupGachaRepo(t *testing.T) (*GachaRepository, *sqlx.DB, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "gacha_test_user") charID := CreateTestCharacter(t, db, userID, "GachaChar") - repo := NewGachaRepository(dbutil.Wrap(db)) + repo := NewGachaRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_goocoo.go b/server/channelserver/repo_goocoo.go index f84608677..dc9c072da 100644 --- a/server/channelserver/repo_goocoo.go +++ b/server/channelserver/repo_goocoo.go @@ -3,16 +3,16 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // GoocooRepository centralizes all database access for the goocoo table. type GoocooRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewGoocooRepository creates a new GoocooRepository. -func NewGoocooRepository(db *dbutil.DB) *GoocooRepository { +func NewGoocooRepository(db *sqlx.DB) *GoocooRepository { return &GoocooRepository{db: db} } diff --git a/server/channelserver/repo_goocoo_test.go b/server/channelserver/repo_goocoo_test.go index a1d8981c7..0b390402d 100644 --- a/server/channelserver/repo_goocoo_test.go +++ b/server/channelserver/repo_goocoo_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -12,7 +11,7 @@ func setupGoocooRepo(t *testing.T) (*GoocooRepository, *sqlx.DB, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "goocoo_test_user") charID := CreateTestCharacter(t, db, userID, "GoocooChar") - repo := NewGoocooRepository(dbutil.Wrap(db)) + repo := NewGoocooRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_guild.go b/server/channelserver/repo_guild.go index a005437d0..f9eca11e5 100644 --- a/server/channelserver/repo_guild.go +++ b/server/channelserver/repo_guild.go @@ -6,19 +6,17 @@ import ( "errors" "fmt" - dbutil "erupe-ce/common/db" - "github.com/jmoiron/sqlx" ) // GuildRepository centralizes all database access for guild-related tables // (guilds, guild_characters, guild_applications). type GuildRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewGuildRepository creates a new GuildRepository. -func NewGuildRepository(db *dbutil.DB) *GuildRepository { +func NewGuildRepository(db *sqlx.DB) *GuildRepository { return &GuildRepository{db: db} } diff --git a/server/channelserver/repo_guild_test.go b/server/channelserver/repo_guild_test.go index 06aae1354..fc2ff6c3c 100644 --- a/server/channelserver/repo_guild_test.go +++ b/server/channelserver/repo_guild_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "fmt" "testing" "time" @@ -14,7 +13,7 @@ func setupGuildRepo(t *testing.T) (*GuildRepository, *sqlx.DB, uint32, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "guild_test_user") charID := CreateTestCharacter(t, db, userID, "GuildLeader") - repo := NewGuildRepository(dbutil.Wrap(db)) + repo := NewGuildRepository(db) guildID := CreateTestGuild(t, db, charID, "TestGuild") t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, guildID, charID @@ -83,7 +82,7 @@ func TestGetByCharIDNotFound(t *testing.T) { func TestCreate(t *testing.T) { db := SetupTestDB(t) defer TeardownTestDB(t, db) - repo := NewGuildRepository(dbutil.Wrap(db)) + repo := NewGuildRepository(db) userID := CreateTestUser(t, db, "create_guild_user") charID := CreateTestCharacter(t, db, userID, "CreateLeader") diff --git a/server/channelserver/repo_house.go b/server/channelserver/repo_house.go index 61185d3f7..f976a71f5 100644 --- a/server/channelserver/repo_house.go +++ b/server/channelserver/repo_house.go @@ -3,17 +3,17 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // HouseRepository centralizes all database access for house-related tables // (user_binary house columns, warehouse, titles). type HouseRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewHouseRepository creates a new HouseRepository. -func NewHouseRepository(db *dbutil.DB) *HouseRepository { +func NewHouseRepository(db *sqlx.DB) *HouseRepository { return &HouseRepository{db: db} } diff --git a/server/channelserver/repo_house_test.go b/server/channelserver/repo_house_test.go index 21ec0a670..2bd841bd7 100644 --- a/server/channelserver/repo_house_test.go +++ b/server/channelserver/repo_house_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -13,7 +12,7 @@ func setupHouseRepo(t *testing.T) (*HouseRepository, *sqlx.DB, uint32) { userID := CreateTestUser(t, db, "house_test_user") charID := CreateTestCharacter(t, db, userID, "HouseChar") CreateTestUserBinary(t, db, charID) - repo := NewHouseRepository(dbutil.Wrap(db)) + repo := NewHouseRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_mail.go b/server/channelserver/repo_mail.go index dbd3a06ae..b9023f6da 100644 --- a/server/channelserver/repo_mail.go +++ b/server/channelserver/repo_mail.go @@ -1,16 +1,16 @@ package channelserver import ( - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // MailRepository centralizes all database access for the mail table. type MailRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewMailRepository creates a new MailRepository. -func NewMailRepository(db *dbutil.DB) *MailRepository { +func NewMailRepository(db *sqlx.DB) *MailRepository { return &MailRepository{db: db} } diff --git a/server/channelserver/repo_mail_test.go b/server/channelserver/repo_mail_test.go index 125f86cfe..101b93ef7 100644 --- a/server/channelserver/repo_mail_test.go +++ b/server/channelserver/repo_mail_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -14,7 +13,7 @@ func setupMailRepo(t *testing.T) (*MailRepository, *sqlx.DB, uint32, uint32) { senderID := CreateTestCharacter(t, db, userID, "Sender") userID2 := CreateTestUser(t, db, "mail_recipient") recipientID := CreateTestCharacter(t, db, userID2, "Recipient") - repo := NewMailRepository(dbutil.Wrap(db)) + repo := NewMailRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, senderID, recipientID } diff --git a/server/channelserver/repo_mercenary.go b/server/channelserver/repo_mercenary.go index da600a34a..e844ae24a 100644 --- a/server/channelserver/repo_mercenary.go +++ b/server/channelserver/repo_mercenary.go @@ -4,16 +4,16 @@ import ( "fmt" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // MercenaryRepository centralizes database access for mercenary/rasta/airou sequences and queries. type MercenaryRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewMercenaryRepository creates a new MercenaryRepository. -func NewMercenaryRepository(db *dbutil.DB) *MercenaryRepository { +func NewMercenaryRepository(db *sqlx.DB) *MercenaryRepository { return &MercenaryRepository{db: db} } diff --git a/server/channelserver/repo_mercenary_test.go b/server/channelserver/repo_mercenary_test.go index 80a5263c7..660b5995b 100644 --- a/server/channelserver/repo_mercenary_test.go +++ b/server/channelserver/repo_mercenary_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -13,7 +12,7 @@ func setupMercenaryRepo(t *testing.T) (*MercenaryRepository, *sqlx.DB, uint32, u userID := CreateTestUser(t, db, "merc_test_user") charID := CreateTestCharacter(t, db, userID, "MercChar") guildID := CreateTestGuild(t, db, charID, "MercGuild") - repo := NewMercenaryRepository(dbutil.Wrap(db)) + repo := NewMercenaryRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID, guildID } diff --git a/server/channelserver/repo_misc.go b/server/channelserver/repo_misc.go index f650fd4bf..f99eaa536 100644 --- a/server/channelserver/repo_misc.go +++ b/server/channelserver/repo_misc.go @@ -3,16 +3,16 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // MiscRepository centralizes database access for miscellaneous game tables. type MiscRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewMiscRepository creates a new MiscRepository. -func NewMiscRepository(db *dbutil.DB) *MiscRepository { +func NewMiscRepository(db *sqlx.DB) *MiscRepository { return &MiscRepository{db: db} } diff --git a/server/channelserver/repo_misc_test.go b/server/channelserver/repo_misc_test.go index ef3b0fbaa..7a16def39 100644 --- a/server/channelserver/repo_misc_test.go +++ b/server/channelserver/repo_misc_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -10,7 +9,7 @@ import ( func setupMiscRepo(t *testing.T) (*MiscRepository, *sqlx.DB) { t.Helper() db := SetupTestDB(t) - repo := NewMiscRepository(dbutil.Wrap(db)) + repo := NewMiscRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db } diff --git a/server/channelserver/repo_rengoku.go b/server/channelserver/repo_rengoku.go index b38fcd3b6..4020667b4 100644 --- a/server/channelserver/repo_rengoku.go +++ b/server/channelserver/repo_rengoku.go @@ -3,16 +3,16 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // RengokuRepository centralizes all database access for the rengoku_score table. type RengokuRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewRengokuRepository creates a new RengokuRepository. -func NewRengokuRepository(db *dbutil.DB) *RengokuRepository { +func NewRengokuRepository(db *sqlx.DB) *RengokuRepository { return &RengokuRepository{db: db} } diff --git a/server/channelserver/repo_rengoku_test.go b/server/channelserver/repo_rengoku_test.go index a1be17a6e..3a8c377e3 100644 --- a/server/channelserver/repo_rengoku_test.go +++ b/server/channelserver/repo_rengoku_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -13,7 +12,7 @@ func setupRengokuRepo(t *testing.T) (*RengokuRepository, *sqlx.DB, uint32, uint3 userID := CreateTestUser(t, db, "rengoku_test_user") charID := CreateTestCharacter(t, db, userID, "RengokuChar") guildID := CreateTestGuild(t, db, charID, "RengokuGuild") - repo := NewRengokuRepository(dbutil.Wrap(db)) + repo := NewRengokuRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID, guildID } diff --git a/server/channelserver/repo_scenario.go b/server/channelserver/repo_scenario.go index 967c3fff0..242e98f6d 100644 --- a/server/channelserver/repo_scenario.go +++ b/server/channelserver/repo_scenario.go @@ -3,16 +3,16 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // ScenarioRepository centralizes all database access for the scenario_counter table. type ScenarioRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewScenarioRepository creates a new ScenarioRepository. -func NewScenarioRepository(db *dbutil.DB) *ScenarioRepository { +func NewScenarioRepository(db *sqlx.DB) *ScenarioRepository { return &ScenarioRepository{db: db} } diff --git a/server/channelserver/repo_scenario_test.go b/server/channelserver/repo_scenario_test.go index 17e43d518..f27694b51 100644 --- a/server/channelserver/repo_scenario_test.go +++ b/server/channelserver/repo_scenario_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -10,7 +9,7 @@ import ( func setupScenarioRepo(t *testing.T) (*ScenarioRepository, *sqlx.DB) { t.Helper() db := SetupTestDB(t) - repo := NewScenarioRepository(dbutil.Wrap(db)) + repo := NewScenarioRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db } diff --git a/server/channelserver/repo_session.go b/server/channelserver/repo_session.go index de9b9ba09..bb8a0dc6e 100644 --- a/server/channelserver/repo_session.go +++ b/server/channelserver/repo_session.go @@ -1,16 +1,16 @@ package channelserver import ( - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // SessionRepository centralizes all database access for sign_sessions and servers tables. type SessionRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewSessionRepository creates a new SessionRepository. -func NewSessionRepository(db *dbutil.DB) *SessionRepository { +func NewSessionRepository(db *sqlx.DB) *SessionRepository { return &SessionRepository{db: db} } diff --git a/server/channelserver/repo_session_test.go b/server/channelserver/repo_session_test.go index e97dc2171..e4d7d78bf 100644 --- a/server/channelserver/repo_session_test.go +++ b/server/channelserver/repo_session_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -14,7 +13,7 @@ func setupSessionRepo(t *testing.T) (*SessionRepository, *sqlx.DB, uint32, uint3 charID := CreateTestCharacter(t, db, userID, "SessionChar") token := "test_token_12345" sessionID := CreateTestSignSession(t, db, userID, token) - repo := NewSessionRepository(dbutil.Wrap(db)) + repo := NewSessionRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, userID, charID, sessionID, token } diff --git a/server/channelserver/repo_shop.go b/server/channelserver/repo_shop.go index 860762d56..04f1c18f1 100644 --- a/server/channelserver/repo_shop.go +++ b/server/channelserver/repo_shop.go @@ -1,16 +1,16 @@ package channelserver import ( - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // ShopRepository centralizes all database access for shop-related tables. type ShopRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewShopRepository creates a new ShopRepository. -func NewShopRepository(db *dbutil.DB) *ShopRepository { +func NewShopRepository(db *sqlx.DB) *ShopRepository { return &ShopRepository{db: db} } diff --git a/server/channelserver/repo_shop_test.go b/server/channelserver/repo_shop_test.go index 1fbc61a40..9a84b1070 100644 --- a/server/channelserver/repo_shop_test.go +++ b/server/channelserver/repo_shop_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -12,7 +11,7 @@ func setupShopRepo(t *testing.T) (*ShopRepository, *sqlx.DB, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "shop_test_user") charID := CreateTestCharacter(t, db, userID, "ShopChar") - repo := NewShopRepository(dbutil.Wrap(db)) + repo := NewShopRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_stamp.go b/server/channelserver/repo_stamp.go index 595becd44..26a9f4d64 100644 --- a/server/channelserver/repo_stamp.go +++ b/server/channelserver/repo_stamp.go @@ -4,16 +4,16 @@ import ( "fmt" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // StampRepository centralizes all database access for the stamps table. type StampRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewStampRepository creates a new StampRepository. -func NewStampRepository(db *dbutil.DB) *StampRepository { +func NewStampRepository(db *sqlx.DB) *StampRepository { return &StampRepository{db: db} } diff --git a/server/channelserver/repo_stamp_test.go b/server/channelserver/repo_stamp_test.go index c8867e02f..ef0b2e556 100644 --- a/server/channelserver/repo_stamp_test.go +++ b/server/channelserver/repo_stamp_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "time" @@ -13,7 +12,7 @@ func setupStampRepo(t *testing.T) (*StampRepository, *sqlx.DB, uint32) { db := SetupTestDB(t) userID := CreateTestUser(t, db, "stamp_test_user") charID := CreateTestCharacter(t, db, userID, "StampChar") - repo := NewStampRepository(dbutil.Wrap(db)) + repo := NewStampRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID } diff --git a/server/channelserver/repo_tower.go b/server/channelserver/repo_tower.go index 8194d815e..1e653476e 100644 --- a/server/channelserver/repo_tower.go +++ b/server/channelserver/repo_tower.go @@ -3,17 +3,17 @@ package channelserver import ( "fmt" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // TowerRepository centralizes all database access for tower-related tables // (tower, guilds tower columns, guild_characters tower columns). type TowerRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewTowerRepository creates a new TowerRepository. -func NewTowerRepository(db *dbutil.DB) *TowerRepository { +func NewTowerRepository(db *sqlx.DB) *TowerRepository { return &TowerRepository{db: db} } diff --git a/server/channelserver/repo_tower_test.go b/server/channelserver/repo_tower_test.go index 5405c9dc1..5c3f2e01a 100644 --- a/server/channelserver/repo_tower_test.go +++ b/server/channelserver/repo_tower_test.go @@ -1,7 +1,6 @@ package channelserver import ( - dbutil "erupe-ce/common/db" "testing" "github.com/jmoiron/sqlx" @@ -18,7 +17,7 @@ func setupTowerRepo(t *testing.T) (*TowerRepository, *sqlx.DB, uint32, uint32) { if _, err := db.Exec("INSERT INTO guild_characters (guild_id, character_id) VALUES ($1, $2)", guildID, charID); err != nil { t.Fatalf("Failed to add char to guild: %v", err) } - repo := NewTowerRepository(dbutil.Wrap(db)) + repo := NewTowerRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, charID, guildID } diff --git a/server/channelserver/repo_user.go b/server/channelserver/repo_user.go index 5e5b8b9d0..919f33dd1 100644 --- a/server/channelserver/repo_user.go +++ b/server/channelserver/repo_user.go @@ -4,16 +4,16 @@ import ( "database/sql" "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // UserRepository centralizes all database access for the users table. type UserRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewUserRepository creates a new UserRepository. -func NewUserRepository(db *dbutil.DB) *UserRepository { +func NewUserRepository(db *sqlx.DB) *UserRepository { return &UserRepository{db: db} } diff --git a/server/channelserver/repo_user_test.go b/server/channelserver/repo_user_test.go index f7f6bdb21..5a95e815c 100644 --- a/server/channelserver/repo_user_test.go +++ b/server/channelserver/repo_user_test.go @@ -2,7 +2,6 @@ package channelserver import ( "database/sql" - dbutil "erupe-ce/common/db" "testing" "time" @@ -13,7 +12,7 @@ func setupUserRepo(t *testing.T) (*UserRepository, *sqlx.DB, uint32) { t.Helper() db := SetupTestDB(t) userID := CreateTestUser(t, db, "user_repo_test") - repo := NewUserRepository(dbutil.Wrap(db)) + repo := NewUserRepository(db) t.Cleanup(func() { TeardownTestDB(t, db) }) return repo, db, userID } diff --git a/server/channelserver/session_lifecycle_integration_test.go b/server/channelserver/session_lifecycle_integration_test.go index b32a3cd7c..f00f6864f 100644 --- a/server/channelserver/session_lifecycle_integration_test.go +++ b/server/channelserver/session_lifecycle_integration_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - dbutil "erupe-ce/common/db" "erupe-ce/common/mhfitem" cfg "erupe-ce/config" "erupe-ce/network/clientctx" @@ -598,19 +597,18 @@ func createTestServerWithDB(t *testing.T, db *sqlx.DB) *Server { server.logger = logger // Initialize repositories - wdb := dbutil.Wrap(db) - server.charRepo = NewCharacterRepository(wdb) - server.guildRepo = NewGuildRepository(wdb) - server.userRepo = NewUserRepository(wdb) - server.gachaRepo = NewGachaRepository(wdb) - server.houseRepo = NewHouseRepository(wdb) - server.festaRepo = NewFestaRepository(wdb) - server.towerRepo = NewTowerRepository(wdb) - server.rengokuRepo = NewRengokuRepository(wdb) - server.mailRepo = NewMailRepository(wdb) - server.stampRepo = NewStampRepository(wdb) - server.distRepo = NewDistributionRepository(wdb) - server.sessionRepo = NewSessionRepository(wdb) + server.charRepo = NewCharacterRepository(db) + server.guildRepo = NewGuildRepository(db) + server.userRepo = NewUserRepository(db) + server.gachaRepo = NewGachaRepository(db) + server.houseRepo = NewHouseRepository(db) + server.festaRepo = NewFestaRepository(db) + server.towerRepo = NewTowerRepository(db) + server.rengokuRepo = NewRengokuRepository(db) + server.mailRepo = NewMailRepository(db) + server.stampRepo = NewStampRepository(db) + server.distRepo = NewDistributionRepository(db) + server.sessionRepo = NewSessionRepository(db) return server } diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index b419b4a17..b569d5dce 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -11,7 +11,6 @@ import ( "time" "erupe-ce/common/byteframe" - dbutil "erupe-ce/common/db" cfg "erupe-ce/config" "erupe-ce/network" "erupe-ce/network/binpacket" @@ -143,28 +142,27 @@ func NewServer(config *Config) *Server { handlerTable: buildHandlerTable(), } - wdb := dbutil.Wrap(config.DB) - s.charRepo = NewCharacterRepository(wdb) - s.guildRepo = NewGuildRepository(wdb) - s.userRepo = NewUserRepository(wdb) - s.gachaRepo = NewGachaRepository(wdb) - s.houseRepo = NewHouseRepository(wdb) - s.festaRepo = NewFestaRepository(wdb) - s.towerRepo = NewTowerRepository(wdb) - s.rengokuRepo = NewRengokuRepository(wdb) - s.mailRepo = NewMailRepository(wdb) - s.stampRepo = NewStampRepository(wdb) - s.distRepo = NewDistributionRepository(wdb) - s.sessionRepo = NewSessionRepository(wdb) - s.eventRepo = NewEventRepository(wdb) - s.achievementRepo = NewAchievementRepository(wdb) - s.shopRepo = NewShopRepository(wdb) - s.cafeRepo = NewCafeRepository(wdb) - s.goocooRepo = NewGoocooRepository(wdb) - s.divaRepo = NewDivaRepository(wdb) - s.miscRepo = NewMiscRepository(wdb) - s.scenarioRepo = NewScenarioRepository(wdb) - s.mercenaryRepo = NewMercenaryRepository(wdb) + s.charRepo = NewCharacterRepository(config.DB) + s.guildRepo = NewGuildRepository(config.DB) + s.userRepo = NewUserRepository(config.DB) + s.gachaRepo = NewGachaRepository(config.DB) + s.houseRepo = NewHouseRepository(config.DB) + s.festaRepo = NewFestaRepository(config.DB) + s.towerRepo = NewTowerRepository(config.DB) + s.rengokuRepo = NewRengokuRepository(config.DB) + s.mailRepo = NewMailRepository(config.DB) + s.stampRepo = NewStampRepository(config.DB) + s.distRepo = NewDistributionRepository(config.DB) + s.sessionRepo = NewSessionRepository(config.DB) + s.eventRepo = NewEventRepository(config.DB) + s.achievementRepo = NewAchievementRepository(config.DB) + s.shopRepo = NewShopRepository(config.DB) + s.cafeRepo = NewCafeRepository(config.DB) + s.goocooRepo = NewGoocooRepository(config.DB) + s.divaRepo = NewDivaRepository(config.DB) + s.miscRepo = NewMiscRepository(config.DB) + s.scenarioRepo = NewScenarioRepository(config.DB) + s.mercenaryRepo = NewMercenaryRepository(config.DB) s.mailService = NewMailService(s.mailRepo, s.guildRepo, s.logger) s.guildService = NewGuildService(s.guildRepo, s.mailService, s.charRepo, s.logger) diff --git a/server/channelserver/testhelpers_db.go b/server/channelserver/testhelpers_db.go index 45bfaa727..5fb6f36ed 100644 --- a/server/channelserver/testhelpers_db.go +++ b/server/channelserver/testhelpers_db.go @@ -8,7 +8,6 @@ import ( "testing" "time" - dbutil "erupe-ce/common/db" "erupe-ce/server/channelserver/compression/nullcomp" "erupe-ce/server/migrations" "github.com/jmoiron/sqlx" @@ -331,26 +330,25 @@ func CreateTestGachaItem(t *testing.T, db *sqlx.DB, entryID uint32, itemType uin // Use this in integration tests instead of setting s.server.db directly. func SetTestDB(s *Server, db *sqlx.DB) { s.db = db - wdb := dbutil.Wrap(db) - s.charRepo = NewCharacterRepository(wdb) - s.guildRepo = NewGuildRepository(wdb) - s.userRepo = NewUserRepository(wdb) - s.gachaRepo = NewGachaRepository(wdb) - s.houseRepo = NewHouseRepository(wdb) - s.festaRepo = NewFestaRepository(wdb) - s.towerRepo = NewTowerRepository(wdb) - s.rengokuRepo = NewRengokuRepository(wdb) - s.mailRepo = NewMailRepository(wdb) - s.stampRepo = NewStampRepository(wdb) - s.distRepo = NewDistributionRepository(wdb) - s.sessionRepo = NewSessionRepository(wdb) - s.eventRepo = NewEventRepository(wdb) - s.achievementRepo = NewAchievementRepository(wdb) - s.shopRepo = NewShopRepository(wdb) - s.cafeRepo = NewCafeRepository(wdb) - s.goocooRepo = NewGoocooRepository(wdb) - s.divaRepo = NewDivaRepository(wdb) - s.miscRepo = NewMiscRepository(wdb) - s.scenarioRepo = NewScenarioRepository(wdb) - s.mercenaryRepo = NewMercenaryRepository(wdb) + s.charRepo = NewCharacterRepository(db) + s.guildRepo = NewGuildRepository(db) + s.userRepo = NewUserRepository(db) + s.gachaRepo = NewGachaRepository(db) + s.houseRepo = NewHouseRepository(db) + s.festaRepo = NewFestaRepository(db) + s.towerRepo = NewTowerRepository(db) + s.rengokuRepo = NewRengokuRepository(db) + s.mailRepo = NewMailRepository(db) + s.stampRepo = NewStampRepository(db) + s.distRepo = NewDistributionRepository(db) + s.sessionRepo = NewSessionRepository(db) + s.eventRepo = NewEventRepository(db) + s.achievementRepo = NewAchievementRepository(db) + s.shopRepo = NewShopRepository(db) + s.cafeRepo = NewCafeRepository(db) + s.goocooRepo = NewGoocooRepository(db) + s.divaRepo = NewDivaRepository(db) + s.miscRepo = NewMiscRepository(db) + s.scenarioRepo = NewScenarioRepository(db) + s.mercenaryRepo = NewMercenaryRepository(db) } diff --git a/server/migrations/migrations.go b/server/migrations/migrations.go index 879dc428c..1172f56fa 100644 --- a/server/migrations/migrations.go +++ b/server/migrations/migrations.go @@ -8,8 +8,6 @@ import ( "strconv" "strings" - dbutil "erupe-ce/common/db" - "github.com/jmoiron/sqlx" "go.uber.org/zap" ) @@ -17,9 +15,6 @@ import ( //go:embed sql/*.sql var migrationFS embed.FS -//go:embed sqlite/*.sql -var sqliteMigrationFS embed.FS - //go:embed seed/*.sql var seedFS embed.FS @@ -27,17 +22,15 @@ var seedFS embed.FS // (auto-marks baseline as applied), then runs all pending migrations in order. // Each migration runs in its own transaction. func Migrate(db *sqlx.DB, logger *zap.Logger) (int, error) { - sqlite := dbutil.IsSQLite(db) - - if err := ensureVersionTable(db, sqlite); err != nil { + if err := ensureVersionTable(db); err != nil { return 0, fmt.Errorf("creating schema_version table: %w", err) } - if err := detectExistingDB(db, logger, sqlite); err != nil { + if err := detectExistingDB(db, logger); err != nil { return 0, fmt.Errorf("detecting existing database: %w", err) } - migrations, err := readMigrations(sqlite) + migrations, err := readMigrations() if err != nil { return 0, fmt.Errorf("reading migration files: %w", err) } @@ -53,7 +46,7 @@ func Migrate(db *sqlx.DB, logger *zap.Logger) (int, error) { continue } logger.Info(fmt.Sprintf("Applying migration %04d: %s", m.version, m.filename)) - if err := applyMigration(db, m, sqlite); err != nil { + if err := applyMigration(db, m); err != nil { return count, fmt.Errorf("applying %s: %w", m.filename, err) } count++ @@ -65,7 +58,6 @@ func Migrate(db *sqlx.DB, logger *zap.Logger) (int, error) { // ApplySeedData runs all seed/*.sql files. Not tracked in schema_version. // Safe to run multiple times if seed files use ON CONFLICT DO NOTHING. func ApplySeedData(db *sqlx.DB, logger *zap.Logger) (int, error) { - sqlite := dbutil.IsSQLite(db) files, err := fs.ReadDir(seedFS, "seed") if err != nil { return 0, fmt.Errorf("reading seed directory: %w", err) @@ -86,11 +78,7 @@ func ApplySeedData(db *sqlx.DB, logger *zap.Logger) (int, error) { return count, fmt.Errorf("reading seed file %s: %w", name, err) } logger.Info(fmt.Sprintf("Applying seed data: %s", name)) - sql := string(data) - if sqlite { - sql = dbutil.Adapt(db, sql) - } - if _, err := db.Exec(sql); err != nil { + if _, err := db.Exec(string(data)); err != nil { return count, fmt.Errorf("executing seed file %s: %w", name, err) } count++ @@ -100,30 +88,20 @@ func ApplySeedData(db *sqlx.DB, logger *zap.Logger) (int, error) { // Version returns the highest applied migration number, or 0 if none. func Version(db *sqlx.DB) (int, error) { - sqlite := dbutil.IsSQLite(db) - var exists bool - if sqlite { - err := db.QueryRow(`SELECT COUNT(*) > 0 FROM sqlite_master - WHERE type='table' AND name='schema_version'`).Scan(&exists) - if err != nil { - return 0, err - } - } else { - err := db.QueryRow(`SELECT EXISTS( - SELECT 1 FROM information_schema.tables - WHERE table_schema = 'public' AND table_name = 'schema_version' - )`).Scan(&exists) - if err != nil { - return 0, err - } + err := db.QueryRow(`SELECT EXISTS( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'public' AND table_name = 'schema_version' + )`).Scan(&exists) + if err != nil { + return 0, err } if !exists { return 0, nil } var version int - err := db.QueryRow("SELECT COALESCE(MAX(version), 0) FROM schema_version").Scan(&version) + err = db.QueryRow("SELECT COALESCE(MAX(version), 0) FROM schema_version").Scan(&version) return version, err } @@ -133,26 +111,18 @@ type migration struct { sql string } -func ensureVersionTable(db *sqlx.DB, sqlite bool) error { - q := `CREATE TABLE IF NOT EXISTS schema_version ( +func ensureVersionTable(db *sqlx.DB) error { + _, err := db.Exec(`CREATE TABLE IF NOT EXISTS schema_version ( version INTEGER PRIMARY KEY, filename TEXT NOT NULL, applied_at TIMESTAMPTZ DEFAULT now() - )` - if sqlite { - q = `CREATE TABLE IF NOT EXISTS schema_version ( - version INTEGER PRIMARY KEY, - filename TEXT NOT NULL, - applied_at TEXT DEFAULT CURRENT_TIMESTAMP - )` - } - _, err := db.Exec(q) + )`) return err } // detectExistingDB checks if the database has tables but no schema_version rows. // If so, it marks the baseline migration (version 1) as already applied. -func detectExistingDB(db *sqlx.DB, logger *zap.Logger, sqlite bool) error { +func detectExistingDB(db *sqlx.DB, logger *zap.Logger) error { var count int if err := db.QueryRow("SELECT COUNT(*) FROM schema_version").Scan(&count); err != nil { return err @@ -163,18 +133,10 @@ func detectExistingDB(db *sqlx.DB, logger *zap.Logger, sqlite bool) error { // Check if the database has any user tables (beyond schema_version itself) var tableCount int - if sqlite { - err := db.QueryRow(`SELECT COUNT(*) FROM sqlite_master - WHERE type='table' AND name != 'schema_version'`).Scan(&tableCount) - if err != nil { - return err - } - } else { - err := db.QueryRow(`SELECT COUNT(*) FROM information_schema.tables - WHERE table_schema = 'public' AND table_name != 'schema_version'`).Scan(&tableCount) - if err != nil { - return err - } + err := db.QueryRow(`SELECT COUNT(*) FROM information_schema.tables + WHERE table_schema = 'public' AND table_name != 'schema_version'`).Scan(&tableCount) + if err != nil { + return err } if tableCount == 0 { return nil // Fresh database @@ -182,22 +144,12 @@ func detectExistingDB(db *sqlx.DB, logger *zap.Logger, sqlite bool) error { // Existing database without migration tracking — mark baseline as applied logger.Info("Detected existing database without schema_version tracking, marking baseline as applied") - _, err := db.Exec("INSERT INTO schema_version (version, filename) VALUES (1, '0001_init.sql')") + _, err = db.Exec("INSERT INTO schema_version (version, filename) VALUES (1, '0001_init.sql')") return err } -func readMigrations(sqlite bool) ([]migration, error) { - var embedFS embed.FS - var dir string - if sqlite { - embedFS = sqliteMigrationFS - dir = "sqlite" - } else { - embedFS = migrationFS - dir = "sql" - } - - files, err := fs.ReadDir(embedFS, dir) +func readMigrations() ([]migration, error) { + files, err := fs.ReadDir(migrationFS, "sql") if err != nil { return nil, err } @@ -211,7 +163,7 @@ func readMigrations(sqlite bool) ([]migration, error) { if err != nil { return nil, fmt.Errorf("parsing version from %s: %w", f.Name(), err) } - data, err := embedFS.ReadFile(dir + "/" + f.Name()) + data, err := migrationFS.ReadFile("sql/" + f.Name()) if err != nil { return nil, err } @@ -254,7 +206,7 @@ func appliedVersions(db *sqlx.DB) (map[int]bool, error) { return applied, rows.Err() } -func applyMigration(db *sqlx.DB, m migration, sqlite bool) error { +func applyMigration(db *sqlx.DB, m migration) error { tx, err := db.Begin() if err != nil { return err @@ -265,11 +217,10 @@ func applyMigration(db *sqlx.DB, m migration, sqlite bool) error { return err } - insertQ := "INSERT INTO schema_version (version, filename) VALUES ($1, $2)" - if sqlite { - insertQ = "INSERT INTO schema_version (version, filename) VALUES (?, ?)" - } - if _, err := tx.Exec(insertQ, m.version, m.filename); err != nil { + if _, err := tx.Exec( + "INSERT INTO schema_version (version, filename) VALUES ($1, $2)", + m.version, m.filename, + ); err != nil { _ = tx.Rollback() return err } diff --git a/server/migrations/migrations_test.go b/server/migrations/migrations_test.go index ee2667ef5..37f3a45b9 100644 --- a/server/migrations/migrations_test.go +++ b/server/migrations/migrations_test.go @@ -8,7 +8,6 @@ import ( "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "go.uber.org/zap" - _ "modernc.org/sqlite" ) func testDB(t *testing.T) *sqlx.DB { @@ -195,7 +194,7 @@ func TestParseVersion(t *testing.T) { } func TestReadMigrations(t *testing.T) { - migrations, err := readMigrations(false) + migrations, err := readMigrations() if err != nil { t.Fatalf("readMigrations failed: %v", err) } @@ -211,7 +210,7 @@ func TestReadMigrations(t *testing.T) { } func TestReadMigrations_Sorted(t *testing.T) { - migrations, err := readMigrations(false) + migrations, err := readMigrations() if err != nil { t.Fatalf("readMigrations failed: %v", err) } @@ -224,7 +223,7 @@ func TestReadMigrations_Sorted(t *testing.T) { } func TestReadMigrations_AllHaveSQL(t *testing.T) { - migrations, err := readMigrations(false) + migrations, err := readMigrations() if err != nil { t.Fatalf("readMigrations failed: %v", err) } @@ -236,7 +235,7 @@ func TestReadMigrations_AllHaveSQL(t *testing.T) { } func TestReadMigrations_BaselineIsLargest(t *testing.T) { - migrations, err := readMigrations(false) + migrations, err := readMigrations() if err != nil { t.Fatalf("readMigrations failed: %v", err) } @@ -253,61 +252,6 @@ func TestReadMigrations_BaselineIsLargest(t *testing.T) { } } -func TestReadMigrations_SQLite(t *testing.T) { - migrations, err := readMigrations(true) - if err != nil { - t.Fatalf("readMigrations(sqlite) failed: %v", err) - } - if len(migrations) != 5 { - t.Fatalf("expected 5 SQLite migrations, got %d", len(migrations)) - } - if migrations[0].filename != "0001_init.sql" { - t.Errorf("first SQLite migration = %q, want 0001_init.sql", migrations[0].filename) - } - for _, m := range migrations { - if m.sql == "" { - t.Errorf("SQLite migration %s has empty SQL", m.filename) - } - } -} - -func TestSQLiteMigrateInMemory(t *testing.T) { - db, err := sqlx.Open("sqlite", ":memory:?_pragma=foreign_keys(1)") - if err != nil { - t.Fatalf("Failed to open in-memory SQLite: %v", err) - } - defer func() { _ = db.Close() }() - - logger, _ := zap.NewDevelopment() - applied, err := Migrate(db, logger) - if err != nil { - t.Fatalf("Migrate to SQLite failed: %v", err) - } - if applied != 5 { - t.Errorf("expected 5 migrations applied, got %d", applied) - } - - ver, err := Version(db) - if err != nil { - t.Fatalf("Version failed: %v", err) - } - if ver != 5 { - t.Errorf("expected version 5, got %d", ver) - } - - // Verify a few key tables exist - for _, table := range []string{"users", "characters", "guilds", "guild_characters", "sign_sessions"} { - var count int - err := db.QueryRow("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?", table).Scan(&count) - if err != nil { - t.Errorf("Failed to check table %s: %v", table, err) - } - if count != 1 { - t.Errorf("Table %s not found in SQLite schema", table) - } - } -} - func TestParseVersion_Comprehensive(t *testing.T) { tests := []struct { filename string diff --git a/server/migrations/sqlite/0001_init.sql b/server/migrations/sqlite/0001_init.sql deleted file mode 100644 index e3624ef61..000000000 --- a/server/migrations/sqlite/0001_init.sql +++ /dev/null @@ -1,855 +0,0 @@ --- Erupe consolidated database schema (SQLite) --- Translated from PostgreSQL 0001_init.sql --- Compatible with modernc.org/sqlite --- --- Includes: init.sql (v9.1.0) + 9.2-update.sql + all 33 patch schemas - -PRAGMA journal_mode=WAL; -PRAGMA foreign_keys=ON; - - --- --- Name: achievements; Type: TABLE --- - -CREATE TABLE achievements ( - id integer NOT NULL, - ach0 integer DEFAULT 0, - ach1 integer DEFAULT 0, - ach2 integer DEFAULT 0, - ach3 integer DEFAULT 0, - ach4 integer DEFAULT 0, - ach5 integer DEFAULT 0, - ach6 integer DEFAULT 0, - ach7 integer DEFAULT 0, - ach8 integer DEFAULT 0, - ach9 integer DEFAULT 0, - ach10 integer DEFAULT 0, - ach11 integer DEFAULT 0, - ach12 integer DEFAULT 0, - ach13 integer DEFAULT 0, - ach14 integer DEFAULT 0, - ach15 integer DEFAULT 0, - ach16 integer DEFAULT 0, - ach17 integer DEFAULT 0, - ach18 integer DEFAULT 0, - ach19 integer DEFAULT 0, - ach20 integer DEFAULT 0, - ach21 integer DEFAULT 0, - ach22 integer DEFAULT 0, - ach23 integer DEFAULT 0, - ach24 integer DEFAULT 0, - ach25 integer DEFAULT 0, - ach26 integer DEFAULT 0, - ach27 integer DEFAULT 0, - ach28 integer DEFAULT 0, - ach29 integer DEFAULT 0, - ach30 integer DEFAULT 0, - ach31 integer DEFAULT 0, - ach32 integer DEFAULT 0, - PRIMARY KEY (id) -); - - --- --- Name: bans; Type: TABLE --- - -CREATE TABLE bans ( - user_id integer NOT NULL, - expires TEXT, - PRIMARY KEY (user_id) -); - - --- --- Name: cafe_accepted; Type: TABLE --- - -CREATE TABLE cafe_accepted ( - cafe_id integer NOT NULL, - character_id integer NOT NULL -); - - --- --- Name: cafebonus; Type: TABLE --- - -CREATE TABLE cafebonus ( - id INTEGER PRIMARY KEY, - time_req integer NOT NULL, - item_type integer NOT NULL, - item_id integer NOT NULL, - quantity integer NOT NULL -); - - --- --- Name: characters; Type: TABLE --- - -CREATE TABLE characters ( - id INTEGER PRIMARY KEY, - user_id bigint, - is_female boolean, - is_new_character boolean, - name TEXT, - unk_desc_string TEXT, - gr INTEGER, - hr INTEGER, - weapon_type INTEGER, - last_login integer, - savedata BLOB, - decomyset BLOB, - hunternavi BLOB, - otomoairou BLOB, - partner BLOB, - platebox BLOB, - platedata BLOB, - platemyset BLOB, - rengokudata BLOB, - savemercenary BLOB, - restrict_guild_scout boolean DEFAULT false NOT NULL, - gacha_items BLOB, - daily_time TEXT, - house_info BLOB, - login_boost BLOB, - skin_hist BLOB, - kouryou_point integer, - gcp integer, - guild_post_checked TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, - time_played integer DEFAULT 0 NOT NULL, - weapon_id integer DEFAULT 0 NOT NULL, - scenariodata BLOB, - savefavoritequest BLOB, - friends text DEFAULT '' NOT NULL, - blocked text DEFAULT '' NOT NULL, - deleted boolean DEFAULT false NOT NULL, - cafe_time integer DEFAULT 0, - netcafe_points integer DEFAULT 0, - boost_time TEXT, - cafe_reset TEXT, - bonus_quests integer DEFAULT 0 NOT NULL, - daily_quests integer DEFAULT 0 NOT NULL, - promo_points integer DEFAULT 0 NOT NULL, - rasta_id integer, - pact_id integer, - stampcard integer DEFAULT 0 NOT NULL, - mezfes BLOB, - FOREIGN KEY (user_id) REFERENCES users(id) -); - - --- --- Name: distribution; Type: TABLE --- - -CREATE TABLE distribution ( - id INTEGER PRIMARY KEY, - character_id integer, - type integer NOT NULL, - deadline TEXT, - event_name text DEFAULT 'GM Gift!' NOT NULL, - description text DEFAULT '~C05You received a gift!' NOT NULL, - times_acceptable integer DEFAULT 1 NOT NULL, - min_hr integer, - max_hr integer, - min_sr integer, - max_sr integer, - min_gr integer, - max_gr integer, - rights integer, - selection boolean -); - - --- --- Name: distribution_items; Type: TABLE --- - -CREATE TABLE distribution_items ( - id INTEGER PRIMARY KEY, - distribution_id integer NOT NULL, - item_type integer NOT NULL, - item_id integer, - quantity integer -); - - --- --- Name: distributions_accepted; Type: TABLE --- - -CREATE TABLE distributions_accepted ( - distribution_id integer, - character_id integer -); - - --- --- Name: event_quests; Type: TABLE --- - -CREATE TABLE event_quests ( - id INTEGER PRIMARY KEY, - max_players integer, - quest_type integer NOT NULL, - quest_id integer NOT NULL, - mark integer, - flags integer, - start_time TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, - active_days integer, - inactive_days integer -); - - --- --- Name: events; Type: TABLE --- - -CREATE TABLE events ( - id INTEGER PRIMARY KEY, - event_type TEXT NOT NULL CHECK (event_type IN ('festa','diva','vs','mezfes')), - start_time TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL -); - - --- --- Name: feature_weapon; Type: TABLE --- - -CREATE TABLE feature_weapon ( - start_time TEXT NOT NULL, - featured integer NOT NULL -); - - --- --- Name: festa_prizes; Type: TABLE --- - -CREATE TABLE festa_prizes ( - id INTEGER PRIMARY KEY, - type TEXT NOT NULL CHECK (type IN ('personal','guild')), - tier integer NOT NULL, - souls_req integer NOT NULL, - item_id integer NOT NULL, - num_item integer NOT NULL -); - - --- --- Name: festa_prizes_accepted; Type: TABLE --- - -CREATE TABLE festa_prizes_accepted ( - prize_id integer NOT NULL, - character_id integer NOT NULL -); - - --- --- Name: festa_registrations; Type: TABLE --- - -CREATE TABLE festa_registrations ( - guild_id integer NOT NULL, - team TEXT NOT NULL CHECK (team IN ('none','red','blue')) -); - - --- --- Name: festa_submissions; Type: TABLE --- - -CREATE TABLE festa_submissions ( - character_id integer NOT NULL, - guild_id integer NOT NULL, - trial_type integer NOT NULL, - souls integer NOT NULL, - "timestamp" TEXT NOT NULL -); - - --- --- Name: festa_trials; Type: TABLE --- - -CREATE TABLE festa_trials ( - id INTEGER PRIMARY KEY, - objective integer NOT NULL, - goal_id integer NOT NULL, - times_req integer NOT NULL, - locale_req integer DEFAULT 0 NOT NULL, - reward integer NOT NULL -); - - --- --- Name: fpoint_items; Type: TABLE --- - -CREATE TABLE fpoint_items ( - id INTEGER PRIMARY KEY, - item_type integer NOT NULL, - item_id integer NOT NULL, - quantity integer NOT NULL, - fpoints integer NOT NULL, - buyable boolean DEFAULT false NOT NULL -); - - --- --- Name: gacha_box; Type: TABLE --- - -CREATE TABLE gacha_box ( - gacha_id integer, - entry_id integer, - character_id integer -); - - --- --- Name: gacha_entries; Type: TABLE --- - -CREATE TABLE gacha_entries ( - id INTEGER PRIMARY KEY, - gacha_id integer, - entry_type integer, - item_type integer, - item_number integer, - item_quantity integer, - weight integer, - rarity integer, - rolls integer, - frontier_points integer, - daily_limit integer, - name text -); - - --- --- Name: gacha_items; Type: TABLE --- - -CREATE TABLE gacha_items ( - id INTEGER PRIMARY KEY, - entry_id integer, - item_type integer, - item_id integer, - quantity integer -); - - --- --- Name: gacha_shop; Type: TABLE --- - -CREATE TABLE gacha_shop ( - id INTEGER PRIMARY KEY, - min_gr integer, - min_hr integer, - name text, - url_banner text, - url_feature text, - url_thumbnail text, - wide boolean, - recommended boolean, - gacha_type integer, - hidden boolean -); - - --- --- Name: gacha_stepup; Type: TABLE --- - -CREATE TABLE gacha_stepup ( - gacha_id integer, - step integer, - character_id integer, - created_at TEXT DEFAULT CURRENT_TIMESTAMP -); - - --- --- Name: goocoo; Type: TABLE --- - -CREATE TABLE goocoo ( - id INTEGER PRIMARY KEY, - goocoo0 BLOB, - goocoo1 BLOB, - goocoo2 BLOB, - goocoo3 BLOB, - goocoo4 BLOB -); - - --- --- Name: guild_adventures; Type: TABLE --- - -CREATE TABLE guild_adventures ( - id INTEGER PRIMARY KEY, - guild_id integer NOT NULL, - destination integer NOT NULL, - charge integer DEFAULT 0 NOT NULL, - depart integer NOT NULL, - "return" integer NOT NULL, - collected_by text DEFAULT '' NOT NULL -); - - --- --- Name: guild_alliances; Type: TABLE --- - -CREATE TABLE guild_alliances ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL, - created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, - parent_id integer NOT NULL, - sub1_id integer, - sub2_id integer -); - - --- --- Name: guild_applications; Type: TABLE --- - -CREATE TABLE guild_applications ( - id INTEGER PRIMARY KEY, - guild_id integer NOT NULL, - character_id integer NOT NULL, - actor_id integer NOT NULL, - application_type TEXT NOT NULL CHECK (application_type IN ('applied','invited')), - created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, - UNIQUE (guild_id, character_id), - FOREIGN KEY (actor_id) REFERENCES characters(id), - FOREIGN KEY (character_id) REFERENCES characters(id), - FOREIGN KEY (guild_id) REFERENCES guilds(id) -); - - --- --- Name: guild_characters; Type: TABLE --- - -CREATE TABLE guild_characters ( - id INTEGER PRIMARY KEY, - guild_id bigint, - character_id bigint, - joined_at TEXT DEFAULT CURRENT_TIMESTAMP, - avoid_leadership boolean DEFAULT false NOT NULL, - order_index integer DEFAULT 1 NOT NULL, - recruiter boolean DEFAULT false NOT NULL, - rp_today integer DEFAULT 0, - rp_yesterday integer DEFAULT 0, - tower_mission_1 integer, - tower_mission_2 integer, - tower_mission_3 integer, - box_claimed TEXT DEFAULT CURRENT_TIMESTAMP, - treasure_hunt integer, - trial_vote integer, - FOREIGN KEY (character_id) REFERENCES characters(id), - FOREIGN KEY (guild_id) REFERENCES guilds(id) -); - - --- --- Name: guild_hunts; Type: TABLE --- - -CREATE TABLE guild_hunts ( - id INTEGER PRIMARY KEY, - guild_id integer NOT NULL, - host_id integer NOT NULL, - destination integer NOT NULL, - level integer NOT NULL, - acquired boolean DEFAULT false NOT NULL, - collected boolean DEFAULT false NOT NULL, - hunt_data BLOB NOT NULL, - cats_used text NOT NULL, - start TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL -); - - --- --- Name: guild_hunts_claimed; Type: TABLE --- - -CREATE TABLE guild_hunts_claimed ( - hunt_id integer NOT NULL, - character_id integer NOT NULL -); - - --- --- Name: guild_meals; Type: TABLE --- - -CREATE TABLE guild_meals ( - id INTEGER PRIMARY KEY, - guild_id integer NOT NULL, - meal_id integer NOT NULL, - level integer NOT NULL, - created_at TEXT -); - - --- --- Name: guild_posts; Type: TABLE --- - -CREATE TABLE guild_posts ( - id INTEGER PRIMARY KEY, - guild_id integer NOT NULL, - author_id integer NOT NULL, - post_type integer NOT NULL, - stamp_id integer NOT NULL, - title text NOT NULL, - body text NOT NULL, - created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, - liked_by text DEFAULT '' NOT NULL, - deleted boolean DEFAULT false NOT NULL -); - - --- --- Name: guilds; Type: TABLE --- - -CREATE TABLE guilds ( - id INTEGER PRIMARY KEY, - name TEXT, - created_at TEXT DEFAULT CURRENT_TIMESTAMP, - leader_id integer NOT NULL, - main_motto integer DEFAULT 0, - rank_rp integer DEFAULT 0 NOT NULL, - comment TEXT DEFAULT '' NOT NULL, - icon BLOB, - sub_motto integer DEFAULT 0, - item_box BLOB, - event_rp integer DEFAULT 0 NOT NULL, - pugi_name_1 TEXT DEFAULT '', - pugi_name_2 TEXT DEFAULT '', - pugi_name_3 TEXT DEFAULT '', - recruiting boolean DEFAULT true NOT NULL, - pugi_outfit_1 integer DEFAULT 0 NOT NULL, - pugi_outfit_2 integer DEFAULT 0 NOT NULL, - pugi_outfit_3 integer DEFAULT 0 NOT NULL, - pugi_outfits integer DEFAULT 0 NOT NULL, - tower_mission_page integer DEFAULT 1, - tower_rp integer DEFAULT 0, - room_rp integer DEFAULT 0, - room_expiry TEXT, - weekly_bonus_users integer DEFAULT 0 NOT NULL, - rp_reset_at TEXT -); - - --- --- Name: kill_logs; Type: TABLE --- - -CREATE TABLE kill_logs ( - id INTEGER PRIMARY KEY, - character_id integer NOT NULL, - monster integer NOT NULL, - quantity integer NOT NULL, - "timestamp" TEXT NOT NULL -); - - --- --- Name: login_boost; Type: TABLE --- - -CREATE TABLE login_boost ( - char_id integer, - week_req integer, - expiration TEXT, - reset TEXT -); - - --- --- Name: mail; Type: TABLE --- - -CREATE TABLE mail ( - id INTEGER PRIMARY KEY, - sender_id integer NOT NULL, - recipient_id integer NOT NULL, - subject TEXT DEFAULT '' NOT NULL, - body TEXT DEFAULT '' NOT NULL, - read boolean DEFAULT false NOT NULL, - attached_item_received boolean DEFAULT false NOT NULL, - attached_item integer, - attached_item_amount integer DEFAULT 1 NOT NULL, - is_guild_invite boolean DEFAULT false NOT NULL, - created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, - deleted boolean DEFAULT false NOT NULL, - locked boolean DEFAULT false NOT NULL, - is_sys_message boolean DEFAULT false NOT NULL, - FOREIGN KEY (recipient_id) REFERENCES characters(id), - FOREIGN KEY (sender_id) REFERENCES characters(id) -); - - --- --- Name: rengoku_score; Type: TABLE --- - -CREATE TABLE rengoku_score ( - character_id integer NOT NULL, - max_stages_mp integer, - max_points_mp integer, - max_stages_sp integer, - max_points_sp integer, - PRIMARY KEY (character_id) -); - - --- --- Name: scenario_counter; Type: TABLE --- - -CREATE TABLE scenario_counter ( - id INTEGER PRIMARY KEY, - scenario_id numeric NOT NULL, - category_id numeric NOT NULL -); - - --- --- Name: servers; Type: TABLE --- - -CREATE TABLE servers ( - server_id integer NOT NULL, - current_players integer NOT NULL, - world_name text, - world_description text, - land integer -); - - --- --- Name: shop_items; Type: TABLE --- - -CREATE TABLE shop_items ( - shop_type integer, - shop_id integer, - id INTEGER PRIMARY KEY, - item_id INTEGER, - cost integer, - quantity INTEGER, - min_hr INTEGER, - min_sr INTEGER, - min_gr INTEGER, - store_level INTEGER, - max_quantity INTEGER, - road_floors INTEGER, - road_fatalis INTEGER -); - - --- --- Name: shop_items_bought; Type: TABLE --- - -CREATE TABLE shop_items_bought ( - character_id integer, - shop_item_id integer, - bought integer -); - -CREATE UNIQUE INDEX IF NOT EXISTS shop_items_bought_character_item_unique - ON shop_items_bought (character_id, shop_item_id); - - --- --- Name: sign_sessions; Type: TABLE --- - -CREATE TABLE sign_sessions ( - user_id integer, - char_id integer, - token TEXT NOT NULL, - server_id integer, - id INTEGER PRIMARY KEY, - psn_id text -); - - --- --- Name: stamps; Type: TABLE --- - -CREATE TABLE stamps ( - character_id integer NOT NULL, - hl_total integer DEFAULT 0, - hl_redeemed integer DEFAULT 0, - hl_checked TEXT, - ex_total integer DEFAULT 0, - ex_redeemed integer DEFAULT 0, - ex_checked TEXT, - monthly_claimed TEXT, - monthly_hl_claimed TEXT, - monthly_ex_claimed TEXT, - PRIMARY KEY (character_id) -); - - --- --- Name: titles; Type: TABLE --- - -CREATE TABLE titles ( - id integer NOT NULL, - char_id integer NOT NULL, - unlocked_at TEXT, - updated_at TEXT -); - - --- --- Name: tower; Type: TABLE --- - -CREATE TABLE tower ( - char_id integer, - tr integer, - trp integer, - tsp integer, - block1 integer, - block2 integer, - skills text, - gems text -); - - --- --- Name: trend_weapons; Type: TABLE --- - -CREATE TABLE trend_weapons ( - weapon_id integer NOT NULL, - weapon_type integer NOT NULL, - count integer DEFAULT 0, - PRIMARY KEY (weapon_id) -); - - --- --- Name: user_binary; Type: TABLE --- - -CREATE TABLE user_binary ( - id INTEGER PRIMARY KEY, - house_tier BLOB, - house_state integer, - house_password text, - house_data BLOB, - house_furniture BLOB, - bookshelf BLOB, - gallery BLOB, - tore BLOB, - garden BLOB, - mission BLOB -); - - --- --- Name: users; Type: TABLE --- - -CREATE TABLE users ( - id INTEGER PRIMARY KEY, - username text NOT NULL UNIQUE, - password text NOT NULL, - item_box BLOB, - rights integer DEFAULT 12 NOT NULL, - last_character integer DEFAULT 0, - last_login TEXT, - return_expires TEXT, - gacha_premium integer, - gacha_trial integer, - frontier_points integer, - psn_id text, - wiiu_key text, - discord_token text, - discord_id text, - op boolean, - timer boolean -); - - --- --- Name: warehouse; Type: TABLE --- - -CREATE TABLE warehouse ( - character_id integer NOT NULL, - item0 BLOB, - item1 BLOB, - item2 BLOB, - item3 BLOB, - item4 BLOB, - item5 BLOB, - item6 BLOB, - item7 BLOB, - item8 BLOB, - item9 BLOB, - item10 BLOB, - item0name text, - item1name text, - item2name text, - item3name text, - item4name text, - item5name text, - item6name text, - item7name text, - item8name text, - item9name text, - equip0 BLOB, - equip1 BLOB, - equip2 BLOB, - equip3 BLOB, - equip4 BLOB, - equip5 BLOB, - equip6 BLOB, - equip7 BLOB, - equip8 BLOB, - equip9 BLOB, - equip10 BLOB, - equip0name text, - equip1name text, - equip2name text, - equip3name text, - equip4name text, - equip5name text, - equip6name text, - equip7name text, - equip8name text, - equip9name text, - PRIMARY KEY (character_id) -); - - --- --- Indexes --- - -CREATE INDEX guild_application_type_index ON guild_applications (application_type); - -CREATE UNIQUE INDEX guild_character_unique_index ON guild_characters (character_id); - -CREATE INDEX mail_recipient_deleted_created_id_index ON mail (recipient_id, deleted, created_at DESC, id DESC); diff --git a/server/migrations/sqlite/0002_catch_up_patches.sql b/server/migrations/sqlite/0002_catch_up_patches.sql deleted file mode 100644 index 938f181ba..000000000 --- a/server/migrations/sqlite/0002_catch_up_patches.sql +++ /dev/null @@ -1,3 +0,0 @@ --- SQLite: no-op. The consolidated 0001_init.sql already includes all patch columns. --- This file exists so the migration version numbering stays in sync with PostgreSQL. -SELECT 1; diff --git a/server/migrations/sqlite/0003_shop_items_bought_unique.sql b/server/migrations/sqlite/0003_shop_items_bought_unique.sql deleted file mode 100644 index 35abff9f7..000000000 --- a/server/migrations/sqlite/0003_shop_items_bought_unique.sql +++ /dev/null @@ -1,2 +0,0 @@ --- SQLite: no-op. The unique index is already in 0001_init.sql. -SELECT 1; diff --git a/server/migrations/sqlite/0004_alliance_recruiting.sql b/server/migrations/sqlite/0004_alliance_recruiting.sql deleted file mode 100644 index 0c123cb58..000000000 --- a/server/migrations/sqlite/0004_alliance_recruiting.sql +++ /dev/null @@ -1,2 +0,0 @@ --- SQLite: no-op. The recruiting column is already in 0001_init.sql. -SELECT 1; diff --git a/server/migrations/sqlite/0005_distribution_drop_data.sql b/server/migrations/sqlite/0005_distribution_drop_data.sql deleted file mode 100644 index 75bdcb878..000000000 --- a/server/migrations/sqlite/0005_distribution_drop_data.sql +++ /dev/null @@ -1,2 +0,0 @@ --- SQLite: no-op. The data column was never included in 0001_init.sql. -SELECT 1; diff --git a/server/signserver/repo_character.go b/server/signserver/repo_character.go index 2cefb8ff3..46ca13f07 100644 --- a/server/signserver/repo_character.go +++ b/server/signserver/repo_character.go @@ -3,17 +3,17 @@ package signserver import ( "strings" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" "github.com/lib/pq" ) // SignCharacterRepository implements SignCharacterRepo with PostgreSQL. type SignCharacterRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewSignCharacterRepository creates a new SignCharacterRepository. -func NewSignCharacterRepository(db *dbutil.DB) *SignCharacterRepository { +func NewSignCharacterRepository(db *sqlx.DB) *SignCharacterRepository { return &SignCharacterRepository{db: db} } diff --git a/server/signserver/repo_session.go b/server/signserver/repo_session.go index 96f722fab..ef654c0e1 100644 --- a/server/signserver/repo_session.go +++ b/server/signserver/repo_session.go @@ -1,14 +1,14 @@ package signserver -import dbutil "erupe-ce/common/db" +import "github.com/jmoiron/sqlx" // SignSessionRepository implements SignSessionRepo with PostgreSQL. type SignSessionRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewSignSessionRepository creates a new SignSessionRepository. -func NewSignSessionRepository(db *dbutil.DB) *SignSessionRepository { +func NewSignSessionRepository(db *sqlx.DB) *SignSessionRepository { return &SignSessionRepository{db: db} } diff --git a/server/signserver/repo_user.go b/server/signserver/repo_user.go index c4f81756a..fa9ee84d2 100644 --- a/server/signserver/repo_user.go +++ b/server/signserver/repo_user.go @@ -3,16 +3,16 @@ package signserver import ( "time" - dbutil "erupe-ce/common/db" + "github.com/jmoiron/sqlx" ) // SignUserRepository implements SignUserRepo with PostgreSQL. type SignUserRepository struct { - db *dbutil.DB + db *sqlx.DB } // NewSignUserRepository creates a new SignUserRepository. -func NewSignUserRepository(db *dbutil.DB) *SignUserRepository { +func NewSignUserRepository(db *sqlx.DB) *SignUserRepository { return &SignUserRepository{db: db} } diff --git a/server/signserver/sign_server.go b/server/signserver/sign_server.go index 261c129c1..4d66ef487 100644 --- a/server/signserver/sign_server.go +++ b/server/signserver/sign_server.go @@ -6,7 +6,6 @@ import ( "net" "sync" - dbutil "erupe-ce/common/db" cfg "erupe-ce/config" "erupe-ce/network" "github.com/jmoiron/sqlx" @@ -39,10 +38,9 @@ func NewServer(config *Config) *Server { erupeConfig: config.ErupeConfig, } if config.DB != nil { - wdb := dbutil.Wrap(config.DB) - s.userRepo = NewSignUserRepository(wdb) - s.charRepo = NewSignCharacterRepository(wdb) - s.sessionRepo = NewSignSessionRepository(wdb) + s.userRepo = NewSignUserRepository(config.DB) + s.charRepo = NewSignCharacterRepository(config.DB) + s.sessionRepo = NewSignSessionRepository(config.DB) } return s }