diff --git a/db/migrations/000001_create_setup.down.sql b/db/migrations/000001_create_setup.down.sql index d0fa079..313e11a 100644 --- a/db/migrations/000001_create_setup.down.sql +++ b/db/migrations/000001_create_setup.down.sql @@ -7,6 +7,10 @@ DROP TABLE IF EXISTS author; DROP TABLE IF EXISTS es_modules; DROP TABLE IF EXISTS scripts; DROP TABLE IF EXISTS tags; +DROP TABLE IF EXISTS relationships_systems; +DROP TABLE IF EXISTS relationships_requires; +DROP TABLE IF EXISTS relationships_recommends; +DROP TABLE IF EXISTS relationships_conflicts; DROP TABLE IF EXISTS relationships; DROP TABLE IF EXISTS compatibility; DROP TABLE IF EXISTS world; diff --git a/db/migrations/000001_create_setup.up.sql b/db/migrations/000001_create_setup.up.sql index 00a52be..40a68f7 100644 --- a/db/migrations/000001_create_setup.up.sql +++ b/db/migrations/000001_create_setup.up.sql @@ -171,9 +171,9 @@ CREATE TABLE IF NOT EXISTS relationships ( ); CREATE TABLE IF NOT EXISTS relationships_systems ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, - relationships_type VARCHAR(32) NOT NULL, + key_ TEXT NOT NULL, type TEXT NOT NULL, manifest TEXT NOT NULL, @@ -182,9 +182,9 @@ CREATE TABLE IF NOT EXISTS relationships_systems ( ); CREATE TABLE IF NOT EXISTS relationships_requires ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, - relationships_type VARCHAR(32) NOT NULL, + key_ INTEGER NOT NULL, type TEXT NOT NULL, manifest TEXT NOT NULL, @@ -193,9 +193,9 @@ CREATE TABLE IF NOT EXISTS relationships_requires ( ); CREATE TABLE IF NOT EXISTS relationships_recommends ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, - relationships_type VARCHAR(32) NOT NULL, + key_ INTEGER NOT NULL, type TEXT NOT NULL, manifest TEXT NOT NULL, @@ -204,9 +204,9 @@ CREATE TABLE IF NOT EXISTS relationships_recommends ( ); CREATE TABLE IF NOT EXISTS relationships_conflicts ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, - relationships_type VARCHAR(32) NOT NULL, + key_ INTEGER NOT NULL, type TEXT NOT NULL, manifest TEXT NOT NULL, @@ -222,17 +222,14 @@ CREATE TABLE IF NOT EXISTS compatibility ( maximum VARCHAR(64) NOT NULL, module_id TEXT UNIQUE, - FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE, - relationships_systems_id TEXT UNIQUE, - FOREIGN KEY (relationships_systems_id) REFERENCES relationships_systems(id) ON DELETE CASCADE - relationships_requires_id TEXT UNIQUE, - FOREIGN KEY (relationships_requires_id) REFERENCES relationships_requires(id) ON DELETE CASCADE - relationships_recommends_id TEXT UNIQUE, - FOREIGN KEY (relationships_recommends_id) REFERENCES relationships_recommends(id) ON DELETE CASCADE - relationships_conflicts_id TEXT UNIQUE, - FOREIGN KEY (relationships_conflicts_id) REFERENCES relationships_conflicts(id) ON DELETE CASCADE + FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE ); +ALTER TABLE compatibility ADD COLUMN relationships_systems_id TEXT REFERENCES relationships_systems(id) ON DELETE CASCADE; +ALTER TABLE compatibility ADD COLUMN relationships_requires_id TEXT REFERENCES relationships_requires(id) ON DELETE CASCADE; +ALTER TABLE compatibility ADD COLUMN relationships_recommends_id TEXT REFERENCES relationships_recommends(id) ON DELETE CASCADE; +ALTER TABLE compatibility ADD COLUMN relationships_conflicts_id TEXT REFERENCES relationships_conflicts(id) ON DELETE CASCADE; + CREATE TABLE IF NOT EXISTS scripts ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -304,8 +301,9 @@ CREATE TABLE IF NOT EXISTS language ( ); CREATE TABLE IF NOT EXISTS pack ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY, + key_ VARCHAR(128) NOT NULL, name VARCHAR(128) NOT NULL, label VARCHAR(128) NOT NULL, banner VARCHAR(128) NOT NULL, @@ -326,7 +324,7 @@ CREATE TABLE IF NOT EXISTS ownership ( trusted VARCHAR(128) NOT NULL, assistant VARCHAR(128) NOT NULL, - pack_id TEXT UNIQUE, + pack_id INTEGER UNIQUE, FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE ); @@ -338,7 +336,7 @@ CREATE TABLE IF NOT EXISTS index_ ( name VARCHAR(128) NOT NULL, type VARCHAR(128) NOT NULL, - pack_id TEXT, + pack_id INTEGER, FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE ); @@ -351,7 +349,7 @@ CREATE TABLE IF NOT EXISTS pack_folder ( type VARCHAR(128) NOT NULL, sort INTEGER NOT NULL, - pack_id TEXT, + pack_id INTEGER, FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE ); @@ -363,15 +361,16 @@ CREATE TABLE IF NOT EXISTS folder ( color VARCHAR(128) NOT NULL, folder_id INTEGER, - FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE, - module_id TEXT, - FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE + FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE ); +ALTER TABLE folder ADD COLUMN module_id TEXT REFERENCES module(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_folder_module_id ON folder(module_id); + CREATE TABLE IF NOT EXISTS folder_packs ( id INTEGER PRIMARY KEY AUTOINCREMENT, - packs VARCHAR(128) NOT NULL, + value VARCHAR(128) NOT NULL, folder_id INTEGER, FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE @@ -390,9 +389,9 @@ CREATE TABLE IF NOT EXISTS news ( ); CREATE TABLE IF NOT EXISTS package_warnings ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, - key_ VARCHAR(128) NOT NULL, + key_ TEXT NOT NULL, setup_id INTEGER, FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE @@ -405,7 +404,7 @@ CREATE TABLE IF NOT EXISTS package_warnings_data ( manifest VARCHAR(128) NOT NULL, reinstallable BOOLEAN NOT NULL, - package_warnings_id TEXT, + package_warnings_id INTEGER, FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE ); @@ -454,9 +453,12 @@ CREATE TABLE IF NOT EXISTS system ( FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE ); -ALTER TABLE compatibility ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id); -ALTER TABLE relationships ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id); -ALTER TABLE document_types ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id); +ALTER TABLE compatibility ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_compatibility_system_id ON compatibility(system_id); +ALTER TABLE relationships ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_relationships_system_id ON relationships(system_id); +ALTER TABLE document_types ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_document_types_system_id ON document_types(system_id); CREATE TABLE IF NOT EXISTS grid ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -475,15 +477,15 @@ CREATE TABLE IF NOT EXISTS grid ( FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE ); -ALTER TABLE es_modules ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE scripts ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE tags ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE author ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE media ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE pack ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE style ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE language ADD COLUMN system_id TEXT REFERENCES system(id); -ALTER TABLE folder ADD COLUMN system_id TEXT REFERENCES system(id); +ALTER TABLE es_modules ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE scripts ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE tags ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE author ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE media ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE pack ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE style ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE language ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE folder ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; CREATE TABLE IF NOT EXISTS world ( id TEXT PRIMARY KEY, @@ -512,15 +514,17 @@ CREATE TABLE IF NOT EXISTS world ( FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE ); -ALTER TABLE compatibility ADD COLUMN world_id TEXT UNIQUE REFERENCES world(id); -ALTER TABLE relationships ADD COLUMN world_id TEXT UNIQUE REFERENCES world(id); +ALTER TABLE compatibility ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_compatibility_world_id ON compatibility(world_id); +ALTER TABLE relationships ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_relationships_world_id ON relationships(world_id); -ALTER TABLE tags ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE scripts ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE es_modules ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE author ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE media ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE style ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE language ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE pack ADD COLUMN world_id TEXT REFERENCES world(id); -ALTER TABLE folder ADD COLUMN world_id TEXT REFERENCES world(id); +ALTER TABLE tags ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE scripts ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE es_modules ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE author ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE media ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE style ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE language ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE pack ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +ALTER TABLE folder ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; diff --git a/db/migrations/000002_create_game.up.sql b/db/migrations/000002_create_game.up.sql index 296449d..311d839 100644 --- a/db/migrations/000002_create_game.up.sql +++ b/db/migrations/000002_create_game.up.sql @@ -361,10 +361,6 @@ CREATE TABLE IF NOT EXISTS active_users ( FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); - - - - CREATE TABLE IF NOT EXISTS item ( id TEXT PRIMARY KEY, @@ -473,7 +469,7 @@ CREATE TABLE IF NOT EXISTS combatant ( ); CREATE TABLE IF NOT EXISTS stats ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, core_version VARCHAR(128) NOT NULL, system_id VARCHAR(128) NOT NULL, @@ -514,7 +510,7 @@ CREATE TABLE IF NOT EXISTS stats ( ); CREATE TABLE IF NOT EXISTS speaker ( - id TEXT PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, scene VARCHAR(128) NOT NULL, actor VARCHAR(128) NOT NULL, @@ -578,7 +574,7 @@ CREATE TABLE IF NOT EXISTS face ( CREATE TABLE IF NOT EXISTS message_whisper ( id TEXT PRIMARY KEY, - whisper VARCHAR(128) NOT NULL, + value VARCHAR(128) NOT NULL, message_id TEXT, FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE @@ -587,7 +583,7 @@ CREATE TABLE IF NOT EXISTS message_whisper ( CREATE TABLE IF NOT EXISTS message_rolls ( id TEXT PRIMARY KEY, - rolls VARCHAR(128) NOT NULL, + value VARCHAR(128) NOT NULL, message_id TEXT, FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE @@ -654,8 +650,6 @@ CREATE TABLE IF NOT EXISTS ownership_string ( FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE ); - - CREATE TABLE IF NOT EXISTS system_update ( id INTEGER PRIMARY KEY AUTOINCREMENT, diff --git a/internal/foundry/temp_models/db/actor.go b/internal/foundry/temp_models/db/actor.go index bb21f03..b620692 100644 --- a/internal/foundry/temp_models/db/actor.go +++ b/internal/foundry/temp_models/db/actor.go @@ -10,6 +10,6 @@ type Actor struct { Sort int PrototypeToken Token Stats Stats - Items []Item + Items []*Item Ownership []OwnershipString } diff --git a/internal/foundry/temp_models/db/addresses.go b/internal/foundry/temp_models/db/addresses.go index 5a5b0dc..8f625fa 100644 --- a/internal/foundry/temp_models/db/addresses.go +++ b/internal/foundry/temp_models/db/addresses.go @@ -1,5 +1,11 @@ package db +import ( + "context" + + "github.com/jmoiron/sqlx" +) + type Addresses struct { ID uint @@ -7,3 +13,40 @@ type Addresses struct { Remote string RemoteIsAccessible bool } + +func (a *Addresses) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO addresses (game_id, local, remote, remote_is_accessible) + VALUES ($1, $2, $3, $4) + RETURNING id` +} + +func (a *Addresses) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, a.Local, a.Remote, a.RemoteIsAccessible} + + err := tx.QueryRowx(data.query, args...).Scan(&a.ID) + if err != nil { + return err + } + + return nil +} + +func (a *Addresses) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, a.Local, a.Remote, a.RemoteIsAccessible} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&a.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/authors.go b/internal/foundry/temp_models/db/authors.go index 19b20ee..586b35c 100644 --- a/internal/foundry/temp_models/db/authors.go +++ b/internal/foundry/temp_models/db/authors.go @@ -31,7 +31,7 @@ func (a *Author) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, a.Name, a.URL, a.Email, a.Discord} - err := tx.QueryRow(data.query, args...).Scan(&a.ID) + err := tx.QueryRowx(data.query, args...).Scan(&a.ID) if err != nil { return err } @@ -46,7 +46,7 @@ func (a *Author) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[stri args := []any{data.id, a.Name, a.URL, a.Email, a.Discord} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&a.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&a.ID) if err != nil { return err } diff --git a/internal/foundry/temp_models/db/card.go b/internal/foundry/temp_models/db/card.go index ef96d89..e80b46e 100644 --- a/internal/foundry/temp_models/db/card.go +++ b/internal/foundry/temp_models/db/card.go @@ -1,5 +1,14 @@ package db +import ( + "context" + "database/sql" + "errors" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type CardDeck struct { ID string @@ -15,7 +24,58 @@ type CardDeck struct { DisplayCount bool Stats Stats Ownership Ownership - Cards []Card + Cards []*Card +} + +func (c *CardDeck) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO card_deck (game_id, id, name, type, description, img, folder, width, height, rotation, sort, display_count) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)` +} + +func (c *CardDeck) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: c.ID, fieldName: "card_deck_id"} + InsertWithCtxParallel(group, ctx, tx, c.Stats, relId) + InsertWithCtxParallel(group, ctx, tx, c.Ownership, relId) + InsertSliceParallel(group, tx, c.Cards, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (c *CardDeck) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.Name, c.Type, c.Description, c.Img, c.Folder, c.Width, c.Height, c.Rotation, c.Sort, c.DisplayCount} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (c *CardDeck) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.Name, c.Type, c.Description, c.Img, c.Folder, c.Width, c.Height, c.Rotation, c.Sort, c.DisplayCount} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil } type Card struct { @@ -38,6 +98,57 @@ type Card struct { Faces []Face } +func (c *Card) Query(data *InsertId[string]) { + data.query = ` + INSERT INTO card (card_deck_id, id, name, type, suit, description, origin, width, height, rotation, value, face, sort, drawn) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)` +} + +func (c *Card) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: c.ID, fieldName: "card_id"} + InsertWithCtxParallel(group, ctx, tx, c.Back, relId) + InsertWithCtxParallel(group, ctx, tx, c.Stats, relId) + InsertSliceParallel(group, tx, c.Faces, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (c *Card) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.Name, c.Type, c.Suit, c.Description, c.Origin, c.Width, c.Height, c.Rotation, c.Value, c.Sort, c.Drawn} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (c *Card) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.Name, c.Type, c.Suit, c.Description, c.Origin, c.Width, c.Height, c.Rotation, c.Value, c.Sort, c.Drawn} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} + type Face struct { ID uint @@ -46,9 +157,83 @@ type Face struct { Text string } +func (f Face) Query(data *InsertId[string]) { + data.query = ` + INSERT INTO face (card_id, name, img, text) + VALUES ($1, $2, $3, $4) + RETURNING id` +} + +func (f Face) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, f.Name, f.Img, f.Text} + + err := tx.QueryRowx(data.query, args...).Scan(&f.ID) + if err != nil { + return err + } + + return nil +} + +func (f Face) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, f.Name, f.Img, f.Text} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&f.ID) + if err != nil { + return err + } + + return nil +} + type Back struct { ID uint Name string Text string } + +func (b Back) Query(data *InsertId[string]) { + data.query = ` + INSERT INTO back (card_id, name, text) + VALUES ($1, $2, $3) + RETURNING id` +} + +func (b Back) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, b.Name, b.Text} + + err := tx.QueryRowx(data.query, args...).Scan(&b.ID) + if err != nil { + return err + } + + return nil +} + +func (b Back) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, b.Name, b.Text} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&b.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/combat.go b/internal/foundry/temp_models/db/combat.go index 2963bf1..93e3cb4 100644 --- a/internal/foundry/temp_models/db/combat.go +++ b/internal/foundry/temp_models/db/combat.go @@ -1,5 +1,14 @@ package db +import ( + "context" + "database/sql" + "errors" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Combat struct { ID string @@ -11,9 +20,58 @@ type Combat struct { Active bool Stats Stats Groups []string - Combatants []Combatant - // System any `json:"system"` - // Flags any `json:"flags"` + Combatants []*Combatant +} + +func (c *Combat) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO combat (game_id, id, type, scene, round, turn, sort, active) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8)` +} + +func (c *Combat) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: c.ID, fieldName: "combat_id", tableName: "combat_groups"} + InsertWithCtxParallel(group, ctx, tx, c.Stats, relId) + InsertSimpleSliceParallel(group, tx, c.Groups, &relId) + InsertSliceParallel(group, tx, c.Combatants, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (c *Combat) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.Type, c.Scene, c.Round, c.Turn, c.Sort, c.Active} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (c *Combat) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.Type, c.Scene, c.Round, c.Turn, c.Sort, c.Active} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil } type Combatant struct { @@ -29,6 +87,53 @@ type Combatant struct { Hidden bool Defeated bool Stats Stats - // System any `json:"system"` - // Flags any `json:"flags"` +} + +func (c *Combatant) Query(data *InsertId[string]) { + data.query = ` + INSERT INTO combatant (combat_id, id, token_id, scene_id, actor_id, img, group_, initiative, hidden, defeated) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)` +} + +func (c *Combatant) InsertObjects(tx *sqlx.Tx) error { + relId := InsertId[string]{id: c.ID, fieldName: "combat_id"} + group, ctx := errgroup.WithContext(context.Background()) + + InsertWithCtxParallel(group, ctx, tx, c.Stats, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (c *Combatant) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.TokenId, c.SceneId, c.ActorId, c.Img, c.Group, c.Initiative, c.Hidden, c.Defeated} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (c *Combatant) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, c.ID, c.TokenId, c.SceneId, c.ActorId, c.Img, c.Group, c.Initiative, c.Hidden, c.Defeated} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil } diff --git a/internal/foundry/temp_models/db/compatibility.go b/internal/foundry/temp_models/db/compatibility.go index 142783b..5cc0532 100644 --- a/internal/foundry/temp_models/db/compatibility.go +++ b/internal/foundry/temp_models/db/compatibility.go @@ -29,7 +29,7 @@ func (c Compatibility) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, c.Minimum, c.Verified, c.Maximum} - err := tx.QueryRow(data.query, args...).Scan(&c.ID) + err := tx.QueryRowx(data.query, args...).Scan(&c.ID) if err != nil { return err } @@ -44,7 +44,7 @@ func (c Compatibility) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertI args := []any{data.id, c.Minimum, c.Verified, c.Maximum} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&c.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&c.ID) if err != nil { return err } diff --git a/internal/foundry/temp_models/db/document_types.go b/internal/foundry/temp_models/db/document_types.go index c939b17..e494252 100644 --- a/internal/foundry/temp_models/db/document_types.go +++ b/internal/foundry/temp_models/db/document_types.go @@ -2,8 +2,12 @@ package db import ( "context" + "database/sql" + "errors" + "fmt" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type DocumentTypes struct { @@ -13,10 +17,10 @@ type DocumentTypes struct { } func (d DocumentTypes) Query(data *InsertId[string]) { - data.query = ` - INSERT INTO document_types (module_id) + data.query = fmt.Sprintf(` + INSERT INTO document_types (%s) VALUES ($1) - RETURNING id` + RETURNING id`, data.fieldName) } func (d DocumentTypes) Insert(tx *sqlx.Tx, data *InsertId[string]) error { @@ -26,16 +30,19 @@ func (d DocumentTypes) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id} - err := tx.QueryRow(data.query, args...).Scan(&d.ID) + err := tx.QueryRowx(data.query, args...).Scan(&d.ID) if err != nil { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) - InsertSliceParallel(syncDB, tx, d.Data, &InsertId[uint]{id: d.ID}) + group, _ := errgroup.WithContext(context.Background()) + InsertSliceParallel(group, tx, d.Data, InsertId[uint]{id: d.ID}) - return syncDB.Wait() + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (d DocumentTypes) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { @@ -45,16 +52,19 @@ func (d DocumentTypes) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertI args := []any{data.id} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&d.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&d.ID) if err != nil { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) - InsertSliceParallel(syncDB, tx, d.Data, &InsertId[uint]{id: d.ID}) + group, _ := errgroup.WithContext(context.Background()) + InsertSliceParallel(group, tx, d.Data, InsertId[uint]{id: d.ID}) - return syncDB.Wait() + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } type DocumentTypeData struct { @@ -78,17 +88,16 @@ func (d *DocumentTypeData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { args := []any{data.id, d.Type} - err := tx.QueryRow(data.query, args...).Scan(&d.ID) + err := tx.QueryRowx(data.query, args...).Scan(&d.ID) if err != nil { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) relData := &InsertId[uint]{id: d.ID, fieldName: "document_types_data_id", tableName: "document_types_data_html"} - InsertSimpleSliceParallel(syncDB, tx, d.HtmlFields, relData) + InsertSimpleSliceParallel(group, tx, d.HtmlFields, relData) - return syncDB.Wait() + return group.Wait() } func (d *DocumentTypeData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { @@ -98,15 +107,14 @@ func (d *DocumentTypeData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *Ins args := []any{data.id, d.Type} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&d.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&d.ID) if err != nil { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) relData := &InsertId[uint]{id: d.ID, fieldName: "document_types_data_id", tableName: "document_types_data_html"} - InsertSimpleSliceParallel(syncDB, tx, d.HtmlFields, relData) + InsertSimpleSliceParallel(group, tx, d.HtmlFields, relData) - return syncDB.Wait() + return group.Wait() } diff --git a/internal/foundry/temp_models/db/files.go b/internal/foundry/temp_models/db/files.go index 3acc061..12de428 100644 --- a/internal/foundry/temp_models/db/files.go +++ b/internal/foundry/temp_models/db/files.go @@ -2,9 +2,12 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type Files struct { @@ -32,12 +35,15 @@ func (f *Files) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) - InsertSliceParallel(syncDB, tx, f.Storages, &InsertId[uint]{id: f.ID}) + InsertSliceParallel(group, tx, f.Storages, InsertId[uint]{id: f.ID}) - return syncDB.Wait() + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (f *Files) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { @@ -52,12 +58,15 @@ func (f *Files) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint] return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) - InsertSliceParallel(syncDB, tx, f.Storages, &InsertId[uint]{id: f.ID}) + InsertSliceParallel(group, tx, f.Storages, InsertId[uint]{id: f.ID}) - return syncDB.Wait() + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } type FilesStorage struct { diff --git a/internal/foundry/temp_models/db/folder.go b/internal/foundry/temp_models/db/folder.go index cda5bde..4f9b7cf 100644 --- a/internal/foundry/temp_models/db/folder.go +++ b/internal/foundry/temp_models/db/folder.go @@ -2,10 +2,13 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "strconv" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type Folder struct { @@ -26,18 +29,21 @@ func (f *Folder) Query(data *InsertId[string]) { } func (f *Folder) InsertObjects(tx *sqlx.Tx) error { - relId := &InsertId[string]{ + relId := InsertId[string]{ id: strconv.FormatUint(uint64(f.ID), 10), fieldName: "folder_id", tableName: "folder_packs", } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) - InsertSimpleSliceParallel(syncDB, tx, f.Packs, relId) - InsertSliceParallel(syncDB, tx, f.Folders, relId) + InsertSimpleSliceParallel(group, tx, f.Packs, &relId) + InsertSliceParallel(group, tx, f.Folders, relId) - return syncDB.Wait() + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (f *Folder) Insert(tx *sqlx.Tx, data *InsertId[string]) error { @@ -47,7 +53,7 @@ func (f *Folder) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, f.Name, f.Sorting, f.Color} - err := tx.QueryRow(data.query, args...).Scan(&f.ID) + err := tx.QueryRowx(data.query, args...).Scan(&f.ID) if err != nil { return err } @@ -62,7 +68,7 @@ func (f *Folder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[stri args := []any{data.id, f.Name, f.Sorting, f.Color} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&f.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&f.ID) if err != nil { return err } @@ -81,5 +87,54 @@ type WorldFolder struct { Color string Sort int Stats Stats - // Flags any `json:"flags,omitempty"` +} + +func (w *WorldFolder) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO world_folder (%s, id, name, type, folder, sorting, description, color, sort) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) + RETURNING id`, data.fieldName) +} + +func (w *WorldFolder) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: w.ID, fieldName: "world_folder_id"} + InsertWithCtxParallel(group, ctx, tx, w.Stats, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (w *WorldFolder) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, w.ID, w.Name, w.Type, w.Folder, w.Sorting, w.Description, w.Color, w.Sort} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return w.InsertObjects(tx) +} + +func (w *WorldFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, w.ID, w.Name, w.Type, w.Folder, w.Sorting, w.Description, w.Color, w.Sort} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return w.InsertObjects(tx) } diff --git a/internal/foundry/temp_models/db/game.go b/internal/foundry/temp_models/db/game.go index f5397c8..573239a 100644 --- a/internal/foundry/temp_models/db/game.go +++ b/internal/foundry/temp_models/db/game.go @@ -1,12 +1,25 @@ package db -type Game struct { - ID uint +import ( + "context" + "database/sql" + "errors" + "strconv" + "time" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + +type Game struct { + ID uint + CreatedAt time.Time + + DemoMode bool + IdleLogout bool + Paused bool + UserID string - DemoMode bool - IdleLogout bool - Paused bool - UserID string Addresses Addresses Files Files Options GameOptions @@ -19,17 +32,83 @@ type Game struct { Modules []*Module PackageWarnings []*PackageWarning Packs []*Pack - Messages []Message - Combats []Combat - CardDeck []CardDeck - Users []User - Macros []Macro - Folders []WorldFolder - Items []Item - Settings []Setting - Journals []Journal - Tables []Table - Playlists []Playlist + Messages []*Message + Combats []*Combat + CardDeck []*CardDeck + Users []*User + Macros []*Macro + Folders []*WorldFolder + Items []*Item + Settings []*Setting + Journals []*Journal + Tables []*Table // + Playlists []*Playlist Actors []Actor // // Scenes []Scene } + +func (g *Game) InsertObjects(tx *sqlx.Tx) error { + relData := InsertId[uint]{id: g.ID, fieldName: "game_id"} + group, ctx := errgroup.WithContext(context.Background()) + + InsertWithCtxParallel(group, ctx, tx, &g.Addresses, relData) + InsertWithCtxParallel(group, ctx, tx, &g.Files, relData) + InsertWithCtxParallel(group, ctx, tx, &g.Options, relData) + InsertWithCtxParallel(group, ctx, tx, &g.Release, relData) + InsertWithCtxParallel(group, ctx, tx, &g.CoreUpdate, relData) + InsertWithCtxParallel(group, ctx, tx, &g.SystemUpdate, relData) + + relDataString := InsertId[string]{id: strconv.FormatUint(uint64(g.ID), 10), fieldName: "game_id"} + InsertWithCtxParallel(group, ctx, tx, g.World, relDataString) + InsertWithCtxParallel(group, ctx, tx, g.System, relDataString) + + InsertSimpleSliceParallel(group, tx, g.ActiveUsers, &InsertId[uint]{id: g.ID, fieldName: "game_id", tableName: "active_users"}) + + InsertSliceParallel(group, tx, g.Modules, relData) + InsertSliceParallel(group, tx, g.PackageWarnings, relData) + InsertSliceParallel(group, tx, g.Packs, relDataString) + InsertSliceParallel(group, tx, g.Messages, relData) + InsertSliceParallel(group, tx, g.Combats, relData) + InsertSliceParallel(group, tx, g.CardDeck, relData) + InsertSliceParallel(group, tx, g.Users, relData) + InsertSliceParallel(group, tx, g.Macros, relData) + InsertSliceParallel(group, tx, g.Folders, relData) + InsertSliceParallel(group, tx, g.Items, relData) + InsertSliceParallel(group, tx, g.Settings, relData) + InsertSliceParallel(group, tx, g.Journals, relData) + InsertSliceParallel(group, tx, g.Tables, relData) + InsertSliceParallel(group, tx, g.Playlists, relData) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (g *Game) Insert(db *sqlx.DB) error { + tx := db.MustBegin() + defer tx.Rollback() + + const query = ` + INSERT INTO game (demo_mode, idle_logout, paused, user_id) + VALUES ($1, $2, $3, $4) + RETURNING id, created_at` + + args := []any{g.DemoMode, g.IdleLogout, g.Paused, g.UserID} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + err := tx.QueryRowxContext(ctx, query, args...).Scan(&g.ID, &g.CreatedAt) + if err != nil { + return err + } + + err = g.InsertObjects(tx) + if err != nil { + return err + } + + return tx.Commit() +} diff --git a/internal/foundry/temp_models/db/grid.go b/internal/foundry/temp_models/db/grid.go index 6c91cda..f1d35d9 100644 --- a/internal/foundry/temp_models/db/grid.go +++ b/internal/foundry/temp_models/db/grid.go @@ -22,7 +22,7 @@ type Grid struct { func (g *Grid) Query(data *InsertId[string]) { data.query = ` - INSERT INTO grid (system_id, type, size, distance, diagonals, thickness + INSERT INTO grid (system_id, type, size, distance, diagonals, thickness, alpha, color, units, style) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id` diff --git a/internal/foundry/temp_models/db/index.go b/internal/foundry/temp_models/db/index.go index cd7d9ad..1e71a58 100644 --- a/internal/foundry/temp_models/db/index.go +++ b/internal/foundry/temp_models/db/index.go @@ -15,14 +15,14 @@ type Index struct { Type string } -func (i *Index) Query(data *InsertId[string]) { +func (i *Index) Query(data *InsertId[uint]) { data.query = ` INSERT INTO index_ (pack_id, id, folder, img, name, type) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id` } -func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[string]) error { +func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } @@ -37,7 +37,7 @@ func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[string]) error { return nil } -func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { +func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } diff --git a/internal/foundry/temp_models/db/item.go b/internal/foundry/temp_models/db/item.go index 5581dd6..76dd316 100644 --- a/internal/foundry/temp_models/db/item.go +++ b/internal/foundry/temp_models/db/item.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Item struct { ID string @@ -11,3 +21,54 @@ type Item struct { Stats Stats Ownership []OwnershipString } + +func (i *Item) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO world_folder (%s, id, img, name, type, folder, sort) + VALUES ($1, $2, $3, $4, $5, $6, $7) + RETURNING id`, data.fieldName) +} + +func (i *Item) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: i.ID, fieldName: "item_id"} + InsertWithCtxParallel(group, ctx, tx, i.Stats, relId) + InsertSliceParallel(group, tx, i.Ownership, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, i.ID, i.Img, i.Name, i.Type, i.Folder, i.Sort} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return i.InsertObjects(tx) +} + +func (i *Item) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, i.ID, i.Img, i.Name, i.Type, i.Folder, i.Sort} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return i.InsertObjects(tx) +} diff --git a/internal/foundry/temp_models/db/journal.go b/internal/foundry/temp_models/db/journal.go index 2c110f3..c5a90e6 100644 --- a/internal/foundry/temp_models/db/journal.go +++ b/internal/foundry/temp_models/db/journal.go @@ -1,10 +1,70 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Journal struct { ID string Name string Sort int - Pages []JournalPage + Pages []*JournalPage Ownership []OwnershipString } + +func (j *Journal) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO journal (%s, id, name, sort) + VALUES ($1, $2, $3, $4)`, data.fieldName) +} + +func (j *Journal) InsertObjects(tx *sqlx.Tx) error { + group, _ := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: j.ID, fieldName: "journal_id"} + InsertSliceParallel(group, tx, j.Pages, relId) + InsertSliceParallel(group, tx, j.Ownership, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (j *Journal) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, j.ID, j.Name, j.Sort} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return j.InsertObjects(tx) +} + +func (j *Journal) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, j.ID, j.Name, j.Sort} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return j.InsertObjects(tx) +} diff --git a/internal/foundry/temp_models/db/journal_page.go b/internal/foundry/temp_models/db/journal_page.go index ca4ec83..3754eb5 100644 --- a/internal/foundry/temp_models/db/journal_page.go +++ b/internal/foundry/temp_models/db/journal_page.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type JournalPage struct { ID string @@ -14,6 +24,60 @@ type JournalPage struct { Ownership []OwnershipString } +func (j *JournalPage) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO journal_page (%s, id, name, type, src, sort) + VALUES ($1, $2, $3, $4, $5, $6)`, data.fieldName) +} + +func (j *JournalPage) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: j.ID, fieldName: "journal_page_id"} + InsertWithCtxParallel(group, ctx, tx, j.Text, relId) + InsertWithCtxParallel(group, ctx, tx, j.Title, relId) + InsertWithCtxParallel(group, ctx, tx, j.Video, relId) + InsertWithCtxParallel(group, ctx, tx, j.Stats, relId) + + InsertSliceParallel(group, tx, j.Ownership, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (j *JournalPage) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, j.ID, j.Name, j.Type, j.Src, j.Sort} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return j.InsertObjects(tx) +} + +func (j *JournalPage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, j.ID, j.Name, j.Type, j.Src, j.Sort} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return j.InsertObjects(tx) +} + type PageText struct { ID uint @@ -22,6 +86,42 @@ type PageText struct { Format int } +func (p PageText) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO journal_page_text (%s, content, markdown, format) + VALUES ($1, $2, $3, $4)`, data.fieldName) +} + +func (p PageText) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.Content, p.Markdown, p.Format} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (p PageText) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.Content, p.Markdown, p.Format} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} + type PageTitle struct { ID uint @@ -29,9 +129,81 @@ type PageTitle struct { Level int } +func (p PageTitle) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO journal_page_title (%s, show, level) + VALUES ($1, $2, $3)`, data.fieldName) +} + +func (p PageTitle) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.Show, p.Level} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (p PageTitle) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.Show, p.Level} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} + type PageVideo struct { ID uint Controls bool Volume float64 } + +func (p PageVideo) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO journal_page_video (%s, controls, volume) + VALUES ($1, $2, $3)`, data.fieldName) +} + +func (p PageVideo) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.Controls, p.Volume} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (p PageVideo) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.Controls, p.Volume} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/language.go b/internal/foundry/temp_models/db/language.go index faeefca..47cb892 100644 --- a/internal/foundry/temp_models/db/language.go +++ b/internal/foundry/temp_models/db/language.go @@ -2,9 +2,12 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type SetupLanguage struct { @@ -33,11 +36,10 @@ func (l *SetupLanguage) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) - InsertSliceParallel(syncDB, tx, l.Modules, &InsertId[string]{id: l.ID}) + group, _ := errgroup.WithContext(context.Background()) + InsertSliceParallel(group, tx, l.Modules, InsertId[string]{id: l.ID}) - return nil + return group.Wait() } func (l *SetupLanguage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { @@ -52,10 +54,13 @@ func (l *SetupLanguage) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *Insert return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) - InsertSliceParallel(syncDB, tx, l.Modules, &InsertId[string]{id: l.ID}) + group, _ := errgroup.WithContext(context.Background()) + InsertSliceParallel(group, tx, l.Modules, InsertId[string]{id: l.ID}) + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } return nil } @@ -125,7 +130,7 @@ func (l *Language) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, l.Lang, l.Name, l.Path} - err := tx.QueryRow(data.query, args...).Scan(&l.ID) + err := tx.QueryRowx(data.query, args...).Scan(&l.ID) if err != nil { return err } @@ -140,7 +145,7 @@ func (l *Language) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[st args := []any{data.id, l.Lang, l.Name, l.Path} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&l.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID) if err != nil { return err } diff --git a/internal/foundry/temp_models/db/macro.go b/internal/foundry/temp_models/db/macro.go index 40b29ca..a927fd3 100644 --- a/internal/foundry/temp_models/db/macro.go +++ b/internal/foundry/temp_models/db/macro.go @@ -1,5 +1,14 @@ package db +import ( + "context" + "database/sql" + "errors" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Macro struct { ID string @@ -14,3 +23,53 @@ type Macro struct { Stats Stats Ownership []OwnershipString } + +func (m *Macro) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO macro (game_id, id, command, name, type, img, author, scope, folder, sort) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8)` +} + +func (m *Macro) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: m.ID, fieldName: "macro_id"} + InsertWithCtxParallel(group, ctx, tx, m.Stats, relId) + InsertSliceParallel(group, tx, m.Ownership, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (m *Macro) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, m.ID, m.Command, m.Name, m.Type, m.Img, m.Author, m.Scope, m.Folder, m.Sort} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (m *Macro) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, m.ID, m.Command, m.Name, m.Type, m.Img, m.Author, m.Scope, m.Folder, m.Sort} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/media.go b/internal/foundry/temp_models/db/media.go index 7c76088..32cb42f 100644 --- a/internal/foundry/temp_models/db/media.go +++ b/internal/foundry/temp_models/db/media.go @@ -29,7 +29,7 @@ func (m *Media) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, m.Type, m.URL, m.Caption} - err := tx.QueryRow(data.query, args...).Scan(&m.ID) + err := tx.QueryRowx(data.query, args...).Scan(&m.ID) if err != nil { return err } @@ -44,7 +44,7 @@ func (m *Media) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[strin args := []any{data.id, m.Type, m.URL, m.Caption} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&m.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&m.ID) if err != nil { return err } diff --git a/internal/foundry/temp_models/db/message.go b/internal/foundry/temp_models/db/message.go index 94d450d..995f884 100644 --- a/internal/foundry/temp_models/db/message.go +++ b/internal/foundry/temp_models/db/message.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Message struct { ID string @@ -18,6 +28,59 @@ type Message struct { Rolls []string } +func (m *Message) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO addresses (game_id, id, blind, emote, style, timestamp, content, author, type, flavor, sound) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)` +} + +func (m *Message) InsertObjects(tx *sqlx.Tx) error { + relId := InsertId[string]{id: m.ID, fieldName: "message_id"} + group, ctx := errgroup.WithContext(context.Background()) + + InsertWithCtxParallel(group, ctx, tx, m.Stats, relId) + InsertWithCtxParallel(group, ctx, tx, m.Speaker, relId) + + InsertSimpleSliceParallel(group, tx, m.Whisper, &InsertId[string]{id: m.ID, fieldName: "message_id", tableName: "message_whisper"}) + InsertSimpleSliceParallel(group, tx, m.Rolls, &InsertId[string]{id: m.ID, fieldName: "message_id", tableName: "message_rolls"}) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (m *Message) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, m.ID, m.Blind, m.Emote, m.Style, m.Timestamp, m.Content, m.Author, m.Type, m.Flavor, m.Sound} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (m *Message) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, m.ID, m.Blind, m.Emote, m.Style, m.Timestamp, m.Content, m.Author, m.Type, m.Flavor, m.Sound} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} + type Speaker struct { ID uint @@ -26,3 +89,39 @@ type Speaker struct { Token string Alias string } + +func (s Speaker) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO speaker (%s, scene, actor, token, alias) + VALUES ($1, $2, $3, $4, $5, $6)`, data.fieldName) +} + +func (s Speaker) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.Scene, s.Actor, s.Token, s.Alias} + + err := tx.QueryRowx(data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} + +func (s Speaker) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.Scene, s.Actor, s.Token, s.Alias} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/module.go b/internal/foundry/temp_models/db/module.go index c3639f0..d5fa000 100644 --- a/internal/foundry/temp_models/db/module.go +++ b/internal/foundry/temp_models/db/module.go @@ -2,9 +2,12 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type Module struct { @@ -55,29 +58,32 @@ func (m *Module) Query(data *InsertId[uint]) { } func (m *Module) InsertObjects(tx *sqlx.Tx) error { - relId := &InsertId[string]{id: m.ID, fieldName: "module_id"} - syncDB := NewSyncDB() - defer close(syncDB.errChan) + relId := InsertId[string]{id: m.ID, fieldName: "module_id"} + group, ctx := errgroup.WithContext(context.Background()) - go InsertWithCtxParallel(syncDB, tx, m.DocumentTypes, relId) - go InsertWithCtxParallel(syncDB, tx, m.Relationships, relId) - go InsertWithCtxParallel(syncDB, tx, m.Compatibility, relId) + InsertWithCtxParallel(group, ctx, tx, m.DocumentTypes, relId) + InsertWithCtxParallel(group, ctx, tx, m.Relationships, relId) + InsertWithCtxParallel(group, ctx, tx, m.Compatibility, relId) - scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"} - go InsertSimpleSliceParallel(syncDB, tx, m.Scripts, scriptRelId) - esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"} - go InsertSimpleSliceParallel(syncDB, tx, m.Esmodules, esModulesRelId) - tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"} - go InsertSimpleSliceParallel(syncDB, tx, m.Tags, tagsRelId) + // scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"} + // InsertSimpleSliceParallel(group, tx, m.Scripts, scriptRelId) + // esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"} + // InsertSimpleSliceParallel(group, tx, m.Esmodules, esModulesRelId) + // tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"} + // InsertSimpleSliceParallel(group, tx, m.Tags, tagsRelId) - go InsertSliceParallel(syncDB, tx, m.Authors, relId) - go InsertSliceParallel(syncDB, tx, m.Media, relId) - go InsertSliceParallel(syncDB, tx, m.Styles, relId) - go InsertSliceParallel(syncDB, tx, m.Languages, relId) - go InsertSliceParallel(syncDB, tx, m.Packs, relId) - go InsertSliceParallel(syncDB, tx, m.PackFolders, relId) + // InsertSliceParallel(group, tx, m.Authors, relId) + // InsertSliceParallel(group, tx, m.Media, relId) + // InsertSliceParallel(group, tx, m.Styles, relId) + // InsertSliceParallel(group, tx, m.Languages, relId) + // InsertSliceParallel(group, tx, m.Packs, relId) + // InsertSliceParallel(group, tx, m.PackFolders, relId) - return syncDB.Wait() + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (m *Module) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { diff --git a/internal/foundry/temp_models/db/options.go b/internal/foundry/temp_models/db/options.go index a29ea1a..515e7f9 100644 --- a/internal/foundry/temp_models/db/options.go +++ b/internal/foundry/temp_models/db/options.go @@ -14,15 +14,21 @@ type GameOptions struct { Port int } -func (g *GameOptions) Insert(tx *sqlx.Tx, gameId *InsertId[uint]) error { - query := ` +func (g *GameOptions) Query(data *InsertId[uint]) { + data.query = ` INSERT INTO featured_content (game_id, language, update_channel, port) VALUES ($1, $2, $3, $4) RETURNING id` +} - args := []any{gameId.id, g.Language, g.UpdateChannel, g.Port} +func (g *GameOptions) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } - err := tx.QueryRowx(query, args...).Scan(&g.ID) + args := []any{data.id, g.Language, g.UpdateChannel, g.Port} + + err := tx.QueryRowx(data.query, args...).Scan(&g.ID) if err != nil { return err } @@ -30,15 +36,14 @@ func (g *GameOptions) Insert(tx *sqlx.Tx, gameId *InsertId[uint]) error { return nil } -func (g *GameOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, gameId *InsertId[uint]) error { - query := ` - INSERT INTO featured_content (game_id, language, update_channel, port) - VALUES ($1, $2, $3, $4) - RETURNING id` +func (g *GameOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } - args := []any{gameId.id, g.Language, g.UpdateChannel, g.Port} + args := []any{data.id, g.Language, g.UpdateChannel, g.Port} - err := tx.QueryRowxContext(ctx, query, args...).Scan(&g.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&g.ID) if err != nil { return err } @@ -71,7 +76,7 @@ func (s *SetupOptions) Query(data *InsertId[uint]) { data.query = ` INSERT INTO setup_options (setup_id, css_theme, data_path, hostname, language, local_hostname, update_channel, port, compress_socket, compress_static, fullscreen, hot_reload, proxy_ssl, - telemetry, upnp, delete_nedb, no_backups,) + telemetry, upnp, delete_nedb, no_backups) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING id` } diff --git a/internal/foundry/temp_models/db/ownership.go b/internal/foundry/temp_models/db/ownership.go index b9ec0f3..51efcf5 100644 --- a/internal/foundry/temp_models/db/ownership.go +++ b/internal/foundry/temp_models/db/ownership.go @@ -2,6 +2,7 @@ package db import ( "context" + "fmt" "github.com/jmoiron/sqlx" ) @@ -15,10 +16,10 @@ type Ownership struct { } func (o Ownership) Query(data *InsertId[string]) { - data.query = ` + data.query = fmt.Sprintf(` INSERT INTO ownership (%s, player, trusted, assistant) VALUES ($1, $2, $3, $4) - RETURNING id` + RETURNING id`, data.fieldName) } func (o Ownership) Insert(tx *sqlx.Tx, data *InsertId[string]) error { @@ -28,7 +29,7 @@ func (o Ownership) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, o.Player, o.Trusted, o.Assistant} - err := tx.QueryRow(data.query, args...).Scan(&o.ID) + err := tx.QueryRowx(data.query, args...).Scan(&o.ID) if err != nil { return err } @@ -43,7 +44,7 @@ func (o Ownership) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[st args := []any{data.id, o.Player, o.Trusted, o.Assistant} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&o.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&o.ID) if err != nil { return err } @@ -57,3 +58,40 @@ type OwnershipString struct { Key string Value int } + +func (o OwnershipString) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO ownership_string (%s, key_, value) + VALUES ($1, $2, $3) + RETURNING id`, data.fieldName) +} + +func (o OwnershipString) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, o.Key, o.Value} + + err := tx.QueryRowx(data.query, args...).Scan(&o.ID) + if err != nil { + return err + } + + return nil +} + +func (o OwnershipString) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, o.Key, o.Value} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&o.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/pack.go b/internal/foundry/temp_models/db/pack.go index f473558..7b2a0a1 100644 --- a/internal/foundry/temp_models/db/pack.go +++ b/internal/foundry/temp_models/db/pack.go @@ -2,14 +2,19 @@ package db import ( "context" + "database/sql" + "errors" "fmt" + "strconv" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type Pack struct { - ID string + ID uint + Key string Name string Label string Banner string @@ -25,21 +30,26 @@ type Pack struct { func (p *Pack) Query(data *InsertId[string]) { data.query = fmt.Sprintf(` - INSERT INTO pack (%s, id, name, label, banner, path, type, system, package_type, package_name) + INSERT INTO pack (%s, key_, name, label, banner, path, type, system, package_type, package_name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id`, data.fieldName) } func (p *Pack) InsertObjects(tx *sqlx.Tx) error { - relId := &InsertId[string]{id: p.ID, fieldName: "pack_id"} - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, ctx := errgroup.WithContext(context.Background()) - InsertWithCtxParallel(syncDB, tx, p.Ownership, relId) - InsertSliceParallel(syncDB, tx, p.Index, relId) - InsertSliceParallel(syncDB, tx, p.Folders, relId) + InsertWithCtxParallel(group, ctx, tx, p.Ownership, + InsertId[string]{id: strconv.FormatUint(uint64(p.ID), 10), fieldName: "pack_id"}) - return syncDB.Wait() + relId := InsertId[uint]{id: p.ID, fieldName: "pack_id"} + InsertSliceParallel(group, tx, p.Index, relId) + InsertSliceParallel(group, tx, p.Folders, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (p *Pack) Insert(tx *sqlx.Tx, data *InsertId[string]) error { @@ -47,9 +57,9 @@ func (p *Pack) Insert(tx *sqlx.Tx, data *InsertId[string]) error { return ErrNoQuery } - args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} + args := []any{data.id, p.Key, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} - _, err := tx.Exec(data.query, args...) + err := tx.QueryRowx(data.query, args...).Scan(&p.ID) if err != nil { return err } @@ -62,9 +72,9 @@ func (p *Pack) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string return ErrNoQuery } - args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} + args := []any{data.id, p.Key, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} - _, err := tx.ExecContext(ctx, data.query, args...) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&p.ID) if err != nil { return err } @@ -82,13 +92,13 @@ type PackFolder struct { Sort int } -func (p *PackFolder) Query(data *InsertId[string]) { +func (p *PackFolder) Query(data *InsertId[uint]) { data.query = fmt.Sprintf(` INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort) VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName) } -func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[string]) error { +func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } @@ -103,7 +113,7 @@ func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[string]) error { return nil } -func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { +func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } diff --git a/internal/foundry/temp_models/db/package_warnings.go b/internal/foundry/temp_models/db/package_warnings.go index dd9f924..e5e7c33 100644 --- a/internal/foundry/temp_models/db/package_warnings.go +++ b/internal/foundry/temp_models/db/package_warnings.go @@ -2,13 +2,16 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type PackageWarning struct { - ID string + ID uint Key string Value *PackageWarningsData @@ -16,8 +19,9 @@ type PackageWarning struct { func (p *PackageWarning) Query(data *InsertId[uint]) { data.query = fmt.Sprintf(` - INSERT INTO package_warnings (%s, id) - VALUES ($1, $2)`, data.fieldName) + INSERT INTO package_warnings (%s, key_) + VALUES ($1, $2) + RETURNING id`, data.fieldName) } func (p *PackageWarning) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { @@ -25,14 +29,14 @@ func (p *PackageWarning) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return ErrNoQuery } - args := []any{data.id, p.ID} + args := []any{data.id, p.Key} - _, err := tx.Exec(data.query, args...) + err := tx.QueryRowx(data.query, args...).Scan(&p.ID) if err != nil { return err } - InsertWithCtx(tx, p.Value, &InsertId[string]{id: p.ID}) + InsertWithCtx(tx, p.Value, InsertId[uint]{id: p.ID}) return nil } @@ -42,16 +46,14 @@ func (p *PackageWarning) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *Inser return ErrNoQuery } - args := []any{data.id, p.ID} + args := []any{data.id, p.Key} - _, err := tx.Exec(data.query, args...) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&p.ID) if err != nil { return err } - InsertWithCtx(tx, p.Value, &InsertId[string]{id: p.ID}) - - return nil + return InsertWithCtx(tx, p.Value, InsertId[uint]{id: p.ID}) } type PackageWarningsData struct { @@ -65,23 +67,27 @@ type PackageWarningsData struct { } func (p *PackageWarningsData) InsertObjects(tx *sqlx.Tx) error { - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) + warningData := &InsertId[string]{id: p.ID, fieldName: "package_warnings_data_id", tableName: "package_warnings_data_warning"} - InsertSimpleSliceParallel(syncDB, tx, p.Warning, warningData) + InsertSimpleSliceParallel(group, tx, p.Warning, warningData) errorData := &InsertId[string]{id: p.ID, fieldName: "package_warnings_data_id", tableName: "package_warnings_data_error"} - InsertSimpleSliceParallel(syncDB, tx, p.Warning, errorData) + InsertSimpleSliceParallel(group, tx, p.Warning, errorData) - return syncDB.Wait() + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } -func (p *PackageWarningsData) Query(data *InsertId[string]) { - data.query = fmt.Sprintf(` - INSERT INTO package_warnings_data (%s, id, type, reinstallable, manifest) - VALUES ($1, $2, $3, $4, $5)`, data.fieldName) +func (p *PackageWarningsData) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO package_warnings_data (package_warnings_id, id, type, reinstallable, manifest) + VALUES ($1, $2, $3, $4, $5)` } -func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[string]) error { +func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } @@ -96,7 +102,7 @@ func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[string]) error return p.InsertObjects(tx) } -func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { +func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } diff --git a/internal/foundry/temp_models/db/playlist.go b/internal/foundry/temp_models/db/playlist.go index 8c96e8a..1a661ab 100644 --- a/internal/foundry/temp_models/db/playlist.go +++ b/internal/foundry/temp_models/db/playlist.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Playlist struct { ID string @@ -15,7 +25,58 @@ type Playlist struct { Playing bool Stats Stats Ownership []OwnershipString - Sounds []Sound + Sounds []*Sound +} + +func (p *Playlist) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO playlist (%s, id, name, folder, sorting, description, channel, mode, fade, seed, sort, playing) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, data.fieldName) +} + +func (p *Playlist) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: p.ID, fieldName: "playlist_id"} + InsertWithCtxParallel(group, ctx, tx, p.Stats, relId) + InsertSliceParallel(group, tx, p.Ownership, relId) + InsertSliceParallel(group, tx, p.Sounds, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (p *Playlist) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.ID, p.Name, p.Folder, p.Sorting, p.Description, p.Channel, p.Mode, p.Fade, p.Seed, p.Sort, p.Playing} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return p.InsertObjects(tx) +} + +func (p *Playlist) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.ID, p.Name, p.Folder, p.Sorting, p.Description, p.Channel, p.Mode, p.Fade, p.Seed, p.Sort, p.Playing} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return p.InsertObjects(tx) } type Sound struct { @@ -32,3 +93,39 @@ type Sound struct { Volume float64 PausedTime float64 } + +func (s *Sound) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO Sound (%s, id, name, path, channel, description, fade, sort, repeat, playing, volume, paused_time) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, data.fieldName) +} + +func (s *Sound) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.ID, s.Name, s.Path, s.Channel, s.Description, s.Fade, s.Sort, s.Repeat, s.Playing, s.Volume, s.PausedTime} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (s *Sound) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.ID, s.Name, s.Path, s.Channel, s.Description, s.Fade, s.Sort, s.Repeat, s.Playing, s.Volume, s.PausedTime} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/relationships.go b/internal/foundry/temp_models/db/relationships.go index ebc8fcb..72e1e63 100644 --- a/internal/foundry/temp_models/db/relationships.go +++ b/internal/foundry/temp_models/db/relationships.go @@ -2,9 +2,13 @@ package db import ( "context" + "database/sql" + "errors" "fmt" + "strconv" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type Relationships struct { @@ -35,15 +39,18 @@ func (r Relationships) Insert(tx *sqlx.Tx, data *InsertId[string]) error { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) - InsertSliceParallel(syncDB, tx, r.Systems, &InsertId[uint]{id: r.ID, tableName: "relationships_systems"}) - InsertSliceParallel(syncDB, tx, r.Requires, &InsertId[uint]{id: r.ID, tableName: "relationships_requires"}) - InsertSliceParallel(syncDB, tx, r.Recommends, &InsertId[uint]{id: r.ID, tableName: "relationships_recommends"}) - InsertSliceParallel(syncDB, tx, r.Conflicts, &InsertId[uint]{id: r.ID, tableName: "relationships_conflicts"}) + InsertSliceParallel(group, tx, r.Systems, InsertId[uint]{id: r.ID, tableName: "relationships_systems"}) + InsertSliceParallel(group, tx, r.Requires, InsertId[uint]{id: r.ID, tableName: "relationships_requires"}) + InsertSliceParallel(group, tx, r.Recommends, InsertId[uint]{id: r.ID, tableName: "relationships_recommends"}) + InsertSliceParallel(group, tx, r.Conflicts, InsertId[uint]{id: r.ID, tableName: "relationships_conflicts"}) - return syncDB.Wait() + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (r Relationships) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { @@ -58,20 +65,24 @@ func (r Relationships) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertI return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) + group, _ := errgroup.WithContext(context.Background()) - InsertSliceParallel(syncDB, tx, r.Systems, &InsertId[uint]{id: r.ID, tableName: "relationships_systems"}) - InsertSliceParallel(syncDB, tx, r.Requires, &InsertId[uint]{id: r.ID, tableName: "relationships_requires"}) - InsertSliceParallel(syncDB, tx, r.Recommends, &InsertId[uint]{id: r.ID, tableName: "relationships_recommends"}) - InsertSliceParallel(syncDB, tx, r.Conflicts, &InsertId[uint]{id: r.ID, tableName: "relationships_conflicts"}) + InsertSliceParallel(group, tx, r.Systems, InsertId[uint]{id: r.ID, tableName: "relationships_systems"}) + InsertSliceParallel(group, tx, r.Requires, InsertId[uint]{id: r.ID, tableName: "relationships_requires"}) + InsertSliceParallel(group, tx, r.Recommends, InsertId[uint]{id: r.ID, tableName: "relationships_recommends"}) + InsertSliceParallel(group, tx, r.Conflicts, InsertId[uint]{id: r.ID, tableName: "relationships_conflicts"}) - return syncDB.Wait() + err = group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } type RelationshipsData struct { - ID string + ID uint + Key string Type string Manifest string Compatibility Compatibility @@ -79,8 +90,8 @@ type RelationshipsData struct { func (r RelationshipsData) Query(data *InsertId[uint]) { data.query = fmt.Sprintf(` - INSERT INTO %s (relationships_id, id, type, manifest) - VALUES ($1, $2, $3, $4, $5)`, data.tableName) + INSERT INTO %s (relationships_id, key_, type, manifest) + VALUES ($1, $2, $3, $4)`, data.tableName) } func (r RelationshipsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { @@ -88,18 +99,17 @@ func (r RelationshipsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return ErrNoQuery } - args := []any{data.id, r.ID, r.Type, r.Manifest} + args := []any{data.id, r.Key, r.Type, r.Manifest} - _, err := tx.Exec(data.query, args...) + err := tx.QueryRowx(data.query, args...).Scan(&r.ID) if err != nil { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) - InsertWithCtxParallel(syncDB, tx, r.Compatibility, &InsertId[string]{id: r.ID, fieldName: fmt.Sprintf("%s_id", data.tableName)}) + group, ctx := errgroup.WithContext(context.Background()) + InsertWithCtxParallel(group, ctx, tx, r.Compatibility, InsertId[string]{id: strconv.FormatUint(uint64(r.ID), 10), fieldName: fmt.Sprintf("%s_id", data.tableName)}) - return nil + return group.Wait() } func (r RelationshipsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { @@ -107,16 +117,15 @@ func (r RelationshipsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *Ins return ErrNoQuery } - args := []any{data.id, r.ID, r.Type, r.Manifest} + args := []any{data.id, r.Key, r.Type, r.Manifest} - _, err := tx.ExecContext(ctx, data.query, args...) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID) if err != nil { return err } - syncDB := NewSyncDB() - defer close(syncDB.errChan) - InsertWithCtxParallel(syncDB, tx, r.Compatibility, &InsertId[string]{id: r.ID, fieldName: fmt.Sprintf("%s_id", data.tableName)}) + group, ctx := errgroup.WithContext(context.Background()) + InsertWithCtxParallel(group, ctx, tx, r.Compatibility, InsertId[string]{id: strconv.FormatUint(uint64(r.ID), 10), fieldName: fmt.Sprintf("%s_id", data.tableName)}) - return nil + return group.Wait() } diff --git a/internal/foundry/temp_models/db/release.go b/internal/foundry/temp_models/db/release.go index fd993fd..10f8486 100644 --- a/internal/foundry/temp_models/db/release.go +++ b/internal/foundry/temp_models/db/release.go @@ -22,7 +22,7 @@ type Release struct { func (r *Release) Query(data *InsertId[uint]) { data.query = fmt.Sprintf(` - INSERT INTO release_ (%s, generaion, build, node_version, max_generation, max_stable_generation, + INSERT INTO release_ (%s, generation, build, node_version, max_generation, max_stable_generation, time, channel, suffix) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`, data.fieldName) diff --git a/internal/foundry/temp_models/db/settings.go b/internal/foundry/temp_models/db/settings.go index 86edeb0..45af818 100644 --- a/internal/foundry/temp_models/db/settings.go +++ b/internal/foundry/temp_models/db/settings.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Setting struct { ID string @@ -7,3 +17,52 @@ type Setting struct { Value string Stats Stats } + +func (s *Setting) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO setting (%s, id, key_, value) + VALUES ($1, $2, $3, $4)`, data.fieldName) +} + +func (s *Setting) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: s.ID, fieldName: "setting_id"} + InsertWithCtxParallel(group, ctx, tx, s.Stats, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (s *Setting) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.ID, s.Key, s.Value} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return s.InsertObjects(tx) +} + +func (s *Setting) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.ID, s.Key, s.Value} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return s.InsertObjects(tx) +} diff --git a/internal/foundry/temp_models/db/setup.go b/internal/foundry/temp_models/db/setup.go index 637c15f..fdd58d2 100644 --- a/internal/foundry/temp_models/db/setup.go +++ b/internal/foundry/temp_models/db/setup.go @@ -2,10 +2,13 @@ package db import ( "context" + "database/sql" + "errors" "strconv" "time" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type Setup struct { @@ -28,29 +31,32 @@ type Setup struct { } func (s *Setup) InsertObjects(tx *sqlx.Tx) error { - relData := &InsertId[uint]{id: s.ID, fieldName: "setup_id"} - syncDB := NewSyncDB() - defer close(syncDB.errChan) + relData := InsertId[uint]{id: s.ID, fieldName: "setup_id"} + group, ctx := errgroup.WithContext(context.Background()) - InsertWithCtxParallel(syncDB, tx, &s.CoreUpdate, relData) - InsertWithCtxParallel(syncDB, tx, &s.FeaturedContent, relData) - InsertWithCtxParallel(syncDB, tx, &s.Files, relData) - InsertWithCtxParallel(syncDB, tx, s.Options, relData) - InsertWithCtxParallel(syncDB, tx, &s.Release, relData) + InsertWithCtxParallel(group, ctx, tx, &s.CoreUpdate, relData) + InsertWithCtxParallel(group, ctx, tx, &s.FeaturedContent, relData) + InsertWithCtxParallel(group, ctx, tx, &s.Files, relData) + InsertWithCtxParallel(group, ctx, tx, s.Options, relData) + InsertWithCtxParallel(group, ctx, tx, &s.Release, relData) - InsertSliceParallel(syncDB, tx, s.Languages, relData) - InsertSliceParallel(syncDB, tx, s.Modules, relData) - InsertSliceParallel(syncDB, tx, s.News, relData) - InsertSliceParallel(syncDB, tx, s.PackageWarnings, relData) + InsertSliceParallel(group, tx, s.Languages, relData) + InsertSliceParallel(group, tx, s.Modules, relData) + InsertSliceParallel(group, tx, s.News, relData) + InsertSliceParallel(group, tx, s.PackageWarnings, relData) - relDataString := &InsertId[string]{ + relDataString := InsertId[string]{ id: strconv.FormatUint(uint64(s.ID), 10), fieldName: "setup_id", } - InsertSliceParallel(syncDB, tx, s.Systems, relDataString) - InsertSliceParallel(syncDB, tx, s.Worlds, relDataString) + InsertSliceParallel(group, tx, s.Systems, relDataString) + InsertSliceParallel(group, tx, s.Worlds, relDataString) - return syncDB.Wait() + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (s *Setup) Insert(db *sqlx.DB) error { @@ -67,7 +73,7 @@ func (s *Setup) Insert(db *sqlx.DB) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - err := tx.QueryRowContext(ctx, query, args...).Scan(&s.ID, &s.CreatedAt) + err := tx.QueryRowxContext(ctx, query, args...).Scan(&s.ID, &s.CreatedAt) if err != nil { return err } @@ -149,7 +155,7 @@ func (n *News) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { args := []any{data.id, n.Title, n.Caption, n.URL, n.Image} - err := tx.QueryRow(data.query, args...).Scan(&n.ID) + err := tx.QueryRowx(data.query, args...).Scan(&n.ID) if err != nil { return err } @@ -164,7 +170,7 @@ func (n *News) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) args := []any{data.id, n.Title, n.Caption, n.URL, n.Image} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&n.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&n.ID) if err != nil { return err } diff --git a/internal/foundry/temp_models/db/stats.go b/internal/foundry/temp_models/db/stats.go index 01211a2..90b4fcf 100644 --- a/internal/foundry/temp_models/db/stats.go +++ b/internal/foundry/temp_models/db/stats.go @@ -1,5 +1,12 @@ package db +import ( + "context" + "fmt" + + "github.com/jmoiron/sqlx" +) + type Stats struct { ID uint @@ -9,3 +16,39 @@ type Stats struct { LastModifiedBy string ModifiedTime int64 } + +func (s Stats) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO stats (%s, core_version, system_id, system_version, last_modified_by, modified_time) + VALUES ($1, $2, $3, $4, $5, $6)`, data.fieldName) +} + +func (s Stats) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.CoreVersion, s.SystemID, s.SystemVersion, s.LastModifiedBy, s.ModifiedTime} + + err := tx.QueryRowx(data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} + +func (s Stats) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.CoreVersion, s.SystemID, s.SystemVersion, s.LastModifiedBy, s.ModifiedTime} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/style.go b/internal/foundry/temp_models/db/style.go index e923c76..f692d3e 100644 --- a/internal/foundry/temp_models/db/style.go +++ b/internal/foundry/temp_models/db/style.go @@ -27,7 +27,7 @@ func (s *Style) Insert(tx *sqlx.Tx, data *InsertId[string]) error { args := []any{data.id, s.Src} - err := tx.QueryRow(data.query, args...).Scan(&s.ID) + err := tx.QueryRowx(data.query, args...).Scan(&s.ID) if err != nil { return err } @@ -42,7 +42,7 @@ func (s *Style) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[strin args := []any{data.id, s.Src} - err := tx.QueryRowContext(ctx, data.query, args...).Scan(&s.ID) + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID) if err != nil { return err } diff --git a/internal/foundry/temp_models/db/system.go b/internal/foundry/temp_models/db/system.go index d0cfac1..b4e0542 100644 --- a/internal/foundry/temp_models/db/system.go +++ b/internal/foundry/temp_models/db/system.go @@ -2,9 +2,12 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type System struct { @@ -54,30 +57,33 @@ func (s *System) Query(data *InsertId[string]) { } func (s *System) InsertObjects(tx *sqlx.Tx) error { - relId := &InsertId[string]{id: s.ID, fieldName: "system_id"} - syncDB := NewSyncDB() - defer close(syncDB.errChan) + relId := InsertId[string]{id: s.ID, fieldName: "system_id"} + group, ctx := errgroup.WithContext(context.Background()) - InsertWithCtxParallel(syncDB, tx, s.Compatibility, relId) - InsertWithCtxParallel(syncDB, tx, s.Relationships, relId) - InsertWithCtxParallel(syncDB, tx, s.DocumentTypes, relId) - InsertWithCtxParallel(syncDB, tx, s.Grid, relId) + InsertWithCtxParallel(group, ctx, tx, s.Compatibility, relId) + InsertWithCtxParallel(group, ctx, tx, s.Relationships, relId) + InsertWithCtxParallel(group, ctx, tx, s.DocumentTypes, relId) + InsertWithCtxParallel(group, ctx, tx, s.Grid, relId) esModulesRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "es_modules"} - InsertSimpleSliceParallel(syncDB, tx, s.Esmodules, esModulesRelId) + InsertSimpleSliceParallel(group, tx, s.Esmodules, esModulesRelId) scriptRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "scripts"} - InsertSimpleSliceParallel(syncDB, tx, s.Scripts, scriptRelId) + InsertSimpleSliceParallel(group, tx, s.Scripts, scriptRelId) tagsRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "tags"} - InsertSimpleSliceParallel(syncDB, tx, s.Tags, tagsRelId) + InsertSimpleSliceParallel(group, tx, s.Tags, tagsRelId) - InsertSliceParallel(syncDB, tx, s.Authors, relId) - InsertSliceParallel(syncDB, tx, s.Media, relId) - InsertSliceParallel(syncDB, tx, s.Styles, relId) - InsertSliceParallel(syncDB, tx, s.Languages, relId) - InsertSliceParallel(syncDB, tx, s.Packs, relId) - InsertSliceParallel(syncDB, tx, s.PackFolders, relId) + InsertSliceParallel(group, tx, s.Authors, relId) + InsertSliceParallel(group, tx, s.Media, relId) + InsertSliceParallel(group, tx, s.Styles, relId) + InsertSliceParallel(group, tx, s.Languages, relId) + InsertSliceParallel(group, tx, s.Packs, relId) + InsertSliceParallel(group, tx, s.PackFolders, relId) - return syncDB.Wait() + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (s *System) Insert(tx *sqlx.Tx, data *InsertId[string]) error { diff --git a/internal/foundry/temp_models/db/table.go b/internal/foundry/temp_models/db/table.go index ddc2fe5..15b0e65 100644 --- a/internal/foundry/temp_models/db/table.go +++ b/internal/foundry/temp_models/db/table.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Table struct { ID string @@ -13,7 +23,58 @@ type Table struct { DisplayRoll bool Stats Stats Ownership []OwnershipString - Results []TableResult + Results []*TableResult +} + +func (t *Table) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO table_ (%s, id, name, description, formula, img, folder, sort, replacement, display_roll) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, data.fieldName) +} + +func (t *Table) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: t.ID, fieldName: "table_id"} + InsertWithCtxParallel(group, ctx, tx, t.Stats, relId) + InsertSliceParallel(group, tx, t.Ownership, relId) + InsertSliceParallel(group, tx, t.Results, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (t *Table) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.ID, t.Name, t.Description, t.Formula, t.Img, t.Folder, t.Sort, t.Replacement, t.DisplayRoll} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return t.InsertObjects(tx) +} + +func (t *Table) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.ID, t.Name, t.Description, t.Formula, t.Img, t.Folder, t.Sort, t.Replacement, t.DisplayRoll} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return t.InsertObjects(tx) } type TableResult struct { @@ -28,3 +89,52 @@ type TableResult struct { Stats Stats Range []int } + +func (t *TableResult) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO table_result (%s, id, type, img, description, name, weight, drawn) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, data.fieldName) +} + +func (t *TableResult) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + InsertWithCtxParallel(group, ctx, tx, t.Stats, InsertId[string]{id: t.ID, fieldName: "table_result_id"}) + InsertSimpleSlice(tx, t.Range, &InsertId[string]{id: t.ID, fieldName: "table_result_id", tableName: "table_result_range"}) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (t *TableResult) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.ID, t.Type, t.Img, t.Description, t.Name, t.Weight, t.Drawn} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return t.InsertObjects(tx) +} + +func (t *TableResult) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.ID, t.Type, t.Img, t.Description, t.Name, t.Weight, t.Drawn} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return t.InsertObjects(tx) +} diff --git a/internal/foundry/temp_models/db/update.go b/internal/foundry/temp_models/db/update.go index 109e909..cbe91cc 100644 --- a/internal/foundry/temp_models/db/update.go +++ b/internal/foundry/temp_models/db/update.go @@ -62,3 +62,40 @@ type SystemUpdate struct { HasUpdate bool Version string } + +func (s *SystemUpdate) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO system_update (%s, has_update, version) + VALUES ($1, $2, $3) + RETURNING id`, data.fieldName) +} + +func (s *SystemUpdate) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.HasUpdate, s.Version} + + err := tx.QueryRowx(data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} + +func (s *SystemUpdate) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.HasUpdate, s.Version} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/user.go b/internal/foundry/temp_models/db/user.go index 2df1553..ae735ce 100644 --- a/internal/foundry/temp_models/db/user.go +++ b/internal/foundry/temp_models/db/user.go @@ -1,5 +1,14 @@ package db +import ( + "context" + "database/sql" + "errors" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type User struct { ID string @@ -13,9 +22,95 @@ type User struct { Hotbar []UserHotbar } +func (u *User) Query(data *InsertId[uint]) { + data.query = ` + INSERT INTO user (game_id, id, name, avatar, character, color, pronouns, role) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8)` +} + +func (u *User) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: u.ID, fieldName: "user_id"} + InsertWithCtxParallel(group, ctx, tx, u.Stats, relId) + InsertSliceParallel(group, tx, u.Hotbar, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (u *User) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, u.ID, u.Name, u.Avatar, u.Character, u.Color, u.Pronouns, u.Role} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (u *User) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, u.ID, u.Name, u.Avatar, u.Character, u.Color, u.Pronouns, u.Role} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} + type UserHotbar struct { ID uint Key int Value string } + +func (u UserHotbar) Query(data *InsertId[string]) { + data.query = ` + INSERT INTO hotbar (user_id, id, key_, value) + VALUES ($1, $2, $3, $4)` +} + +func (u UserHotbar) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, u.ID, u.Key, u.Value} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return nil +} + +func (u UserHotbar) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, u.ID, u.Key, u.Value} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/utils.go b/internal/foundry/temp_models/db/utils.go index 903dc9b..ddf09d9 100644 --- a/internal/foundry/temp_models/db/utils.go +++ b/internal/foundry/temp_models/db/utils.go @@ -4,14 +4,15 @@ import ( "context" "errors" "fmt" - "sync" "time" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) var ( - ErrNoQuery = errors.New("Query has not been set") + ErrNoQuery = errors.New("Query has not been set") + ErrorRecordNotFound = errors.New("Record not found") ) type AllowedIds interface { @@ -25,75 +26,40 @@ type InsertId[T AllowedIds] struct { query string } -type SyncDB struct { - errChan chan error - wg sync.WaitGroup -} - -func NewSyncDB() *SyncDB { - return &SyncDB{ - wg: sync.WaitGroup{}, - errChan: make(chan error), - } -} - -func (s *SyncDB) Wait() error { - return WaitSync(&s.wg, s.errChan) -} - -func WaitSync(wg *sync.WaitGroup, errChan chan error) error { - wgDone := make(chan struct{}) - - go func() { - wg.Wait() - close(wgDone) - }() - - select { - case <-wgDone: - return nil - case err := <-errChan: - close(wgDone) - return err - } -} - type Insertable[T AllowedIds] interface { Query(data *InsertId[T]) Insert(tx *sqlx.Tx, relId *InsertId[T]) error InsertCtx(ctx context.Context, tx *sqlx.Tx, relId *InsertId[T]) error } -func InsertWithCtx[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data I, relId *InsertId[T]) error { +func InsertWithCtx[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data I, relId InsertId[T]) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - data.Query(relId) - return data.InsertCtx(ctx, tx, relId) + data.Query(&relId) + return data.InsertCtx(ctx, tx, &relId) } -func InsertWithCtxParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDB, tx *sqlx.Tx, data I, relId *InsertId[T]) { - syncDb.wg.Go(func() { +func InsertWithCtxParallel[T AllowedIds, I Insertable[T]](g *errgroup.Group, ctx context.Context, tx *sqlx.Tx, data I, relId InsertId[T]) { + g.Go(func() error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - data.Query(relId) - err := data.InsertCtx(ctx, tx, relId) - if err != nil { - syncDb.errChan <- err - } + data.Query(&relId) + err := data.InsertCtx(ctx, tx, &relId) + return err }) } -func InsertSlice[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId *InsertId[T]) error { +func InsertSlice[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId InsertId[T]) error { ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel() if len(data) > 0 { - data[0].Query(relId) + data[0].Query(&relId) } for i := range data { - err := data[i].InsertCtx(ctx, tx, relId) + err := data[i].InsertCtx(ctx, tx, &relId) if err != nil { return err } @@ -101,32 +67,25 @@ func InsertSlice[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId *In return nil } -func InsertSliceParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDB, tx *sqlx.Tx, data []I, relId *InsertId[T]) { - syncDb.wg.Go(func() { - wg := sync.WaitGroup{} - errChan := make(chan error) - defer close(errChan) +func InsertSliceParallel[T AllowedIds, I Insertable[T]](g *errgroup.Group, tx *sqlx.Tx, data []I, relId InsertId[T]) { + g.Go(func() error { + wg, _ := errgroup.WithContext(context.Background()) var err error if len(data) > 0 { - data[0].Query(relId) + data[0].Query(&relId) } for i := range data { - wg.Go(func() { + wg.Go(func() error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - err = data[i].InsertCtx(ctx, tx, relId) - if err != nil { - errChan <- err - } + err = data[i].InsertCtx(ctx, tx, &relId) + return err }) } - err = WaitSync(&wg, errChan) - if err != nil { - syncDb.errChan <- err - } + return wg.Wait() }) } @@ -147,30 +106,69 @@ func InsertSimpleSlice[T AllowedIds, I any](tx *sqlx.Tx, data []I, relId *Insert return nil } -func InsertSimpleSliceParallel[T AllowedIds, I any](syncDb *SyncDB, tx *sqlx.Tx, data []I, relId *InsertId[T]) { - syncDb.wg.Go(func() { - wg := sync.WaitGroup{} - errChan := make(chan error) - defer close(errChan) +func InsertSimpleSliceParallel[T AllowedIds, I any](g *errgroup.Group, tx *sqlx.Tx, data []I, relId *InsertId[T]) { + g.Go(func() error { + wg, _ := errgroup.WithContext(context.Background()) query := fmt.Sprintf(` INSERT INTO %s (%s, value) VALUES ($1, $2)`, relId.tableName, relId.fieldName) for i := range data { - wg.Go(func() { + wg.Go(func() error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() _, err := tx.ExecContext(ctx, query, relId.id, data[i]) - if err != nil { - errChan <- err - } + return err }) } - err := WaitSync(&wg, errChan) - if err != nil { - syncDb.errChan <- err - } + return wg.Wait() }) } + +func DeleteAll(db *sqlx.DB) error { + query := ` + DELETE FROM setup` + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + result, err := db.ExecContext(ctx, query) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + if rowsAffected == 0 { + return ErrorRecordNotFound + } + + return nil +} + +func DeleteAllSeq(db *sqlx.DB) error { + query := ` + DELETE FROM sqlite_sequence` + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + result, err := db.ExecContext(ctx, query) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + if rowsAffected == 0 { + return ErrorRecordNotFound + } + + return nil +} diff --git a/internal/foundry/temp_models/db/world.go b/internal/foundry/temp_models/db/world.go index 9036890..5303ee4 100644 --- a/internal/foundry/temp_models/db/world.go +++ b/internal/foundry/temp_models/db/world.go @@ -2,10 +2,13 @@ package db import ( "context" + "database/sql" + "errors" "fmt" "time" "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" ) type World struct { @@ -53,28 +56,31 @@ func (w *World) Query(data *InsertId[string]) { } func (w *World) InsertObjects(tx *sqlx.Tx) error { - relId := &InsertId[string]{id: w.ID, fieldName: "world_id"} - syncDB := NewSyncDB() - defer close(syncDB.errChan) + relId := InsertId[string]{id: w.ID, fieldName: "world_id"} + group, ctx := errgroup.WithContext(context.Background()) - InsertWithCtxParallel(syncDB, tx, w.Compatibility, relId) - InsertWithCtxParallel(syncDB, tx, w.Relationships, relId) + InsertWithCtxParallel(group, ctx, tx, w.Compatibility, relId) + InsertWithCtxParallel(group, ctx, tx, w.Relationships, relId) esModulesRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "es_modules"} - InsertSimpleSliceParallel(syncDB, tx, w.Esmodules, esModulesRelId) + InsertSimpleSliceParallel(group, tx, w.Esmodules, esModulesRelId) scriptRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "scripts"} - InsertSimpleSliceParallel(syncDB, tx, w.Scripts, scriptRelId) + InsertSimpleSliceParallel(group, tx, w.Scripts, scriptRelId) tagsRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "tags"} - InsertSimpleSliceParallel(syncDB, tx, w.Tags, tagsRelId) + InsertSimpleSliceParallel(group, tx, w.Tags, tagsRelId) - InsertSliceParallel(syncDB, tx, w.Authors, relId) - InsertSliceParallel(syncDB, tx, w.Media, relId) - InsertSliceParallel(syncDB, tx, w.Styles, relId) - InsertSliceParallel(syncDB, tx, w.Languages, relId) - InsertSliceParallel(syncDB, tx, w.Packs, relId) - InsertSliceParallel(syncDB, tx, w.PackFolders, relId) + InsertSliceParallel(group, tx, w.Authors, relId) + InsertSliceParallel(group, tx, w.Media, relId) + InsertSliceParallel(group, tx, w.Styles, relId) + InsertSliceParallel(group, tx, w.Languages, relId) + InsertSliceParallel(group, tx, w.Packs, relId) + InsertSliceParallel(group, tx, w.PackFolders, relId) - return syncDB.Wait() + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil } func (w *World) Insert(tx *sqlx.Tx, data *InsertId[string]) error { diff --git a/internal/foundry/temp_models/json/card.go b/internal/foundry/temp_models/json/card.go index c82d50e..f750ca5 100644 --- a/internal/foundry/temp_models/json/card.go +++ b/internal/foundry/temp_models/json/card.go @@ -21,27 +21,31 @@ type CardDeck struct { // Cards0System any `json:"system"` } -func (c *CardDeck) ToDB(dest *db.CardDeck) bool { +func (c *CardDeck) ToDB(dest **db.CardDeck) bool { if dest == nil { return false } - dest.Name = c.Name - dest.Type = c.Type - dest.Description = c.Description - dest.Img = c.Img - dest.Width = c.Width - dest.Height = c.Height - dest.Rotation = c.Rotation - dest.DisplayCount = c.DisplayCount - dest.Folder = c.Folder - dest.Sort = c.Sort - dest.ID = c.ID + cardDeck := &db.CardDeck{ + Name: c.Name, + Type: c.Type, + Description: c.Description, + Img: c.Img, + Width: c.Width, + Height: c.Height, + Rotation: c.Rotation, + DisplayCount: c.DisplayCount, + Folder: c.Folder, + Sort: c.Sort, + ID: c.ID, + } - c.Stats.ToDB(&dest.Stats) - c.Ownership.ToDB(&dest.Ownership) + c.Stats.ToDB(&cardDeck.Stats) + c.Ownership.ToDB(&cardDeck.Ownership) - CopySliceToDB(&dest.Cards, c.Cards) + CopySliceToDB(&cardDeck.Cards, c.Cards) + + *dest = cardDeck return true } @@ -67,29 +71,33 @@ type Card struct { // System any `json:"system"` } -func (c *Card) ToDB(dest *db.Card) bool { +func (c *Card) ToDB(dest **db.Card) bool { if dest == nil { return false } - dest.Name = c.Name - dest.Width = c.Width - dest.Height = c.Height - dest.Rotation = c.Rotation - dest.Type = c.Type - dest.Value = c.Value - dest.Suit = c.Suit - dest.Description = c.Description - dest.Face = c.Face - dest.Drawn = c.Drawn - dest.Origin = c.Origin - dest.ID = c.ID - dest.Sort = c.Sort + card := &db.Card{ + Name: c.Name, + Width: c.Width, + Height: c.Height, + Rotation: c.Rotation, + Type: c.Type, + Value: c.Value, + Suit: c.Suit, + Description: c.Description, + Face: c.Face, + Drawn: c.Drawn, + Origin: c.Origin, + ID: c.ID, + Sort: c.Sort, + } - c.Back.ToDB(&dest.Back) - c.Stats.ToDB(&dest.Stats) + c.Back.ToDB(&card.Back) + c.Stats.ToDB(&card.Stats) - CopySliceToDB(&dest.Faces, c.Faces) + CopySliceToDB(&card.Faces, c.Faces) + + *dest = card return true } diff --git a/internal/foundry/temp_models/json/combat.go b/internal/foundry/temp_models/json/combat.go index def1ac8..578bf13 100644 --- a/internal/foundry/temp_models/json/combat.go +++ b/internal/foundry/temp_models/json/combat.go @@ -17,23 +17,28 @@ type Combat struct { // Flags any `json:"flags"` } -func (c *Combat) ToDB(dest *db.Combat) bool { +func (c *Combat) ToDB(dest **db.Combat) bool { if dest == nil { return false } - dest.ID = c.Id - dest.Type = c.Type - dest.Scene = c.Scene - dest.Active = c.Active - dest.Round = c.Round - dest.Turn = c.Turn - dest.Sort = c.Sort + combat := &db.Combat{ + ID: c.Id, + Type: c.Type, + Scene: c.Scene, + Active: c.Active, + Round: c.Round, + Turn: c.Turn, + Sort: c.Sort, + } - c.Stats.ToDB(&dest.Stats) + c.Stats.ToDB(&combat.Stats) - copy(dest.Groups, c.Groups) - CopySliceToDB(&dest.Combatants, c.Combatants) + combat.Groups = make([]string, len(c.Groups)) + copy(combat.Groups, c.Groups) + CopySliceToDB(&combat.Combatants, c.Combatants) + + *dest = combat return true } @@ -54,22 +59,27 @@ type Combatant struct { // Flags any `json:"flags"` } -func (c *Combatant) ToDB(dest *db.Combatant) bool { +func (c *Combatant) ToDB(dest **db.Combatant) bool { if dest == nil { return false } - dest.TokenId = c.TokenId - dest.SceneId = c.SceneId - dest.ActorId = c.ActorId - dest.Hidden = c.Hidden - dest.ID = c.Id - dest.Type = c.Type - dest.Img = c.Img - dest.Initiative = c.Initiative - dest.Defeated = c.Defeated - dest.Group = c.Group - c.Stats.ToDB(&dest.Stats) + combatant := &db.Combatant{ + TokenId: c.TokenId, + SceneId: c.SceneId, + ActorId: c.ActorId, + Hidden: c.Hidden, + ID: c.Id, + Type: c.Type, + Img: c.Img, + Initiative: c.Initiative, + Defeated: c.Defeated, + Group: c.Group, + } + + c.Stats.ToDB(&combatant.Stats) + + *dest = combatant return true } diff --git a/internal/foundry/temp_models/json/document_types.go b/internal/foundry/temp_models/json/document_types.go index c3222bd..4f8c981 100644 --- a/internal/foundry/temp_models/json/document_types.go +++ b/internal/foundry/temp_models/json/document_types.go @@ -15,11 +15,11 @@ func (d *DocumentTypes) ToDB(dest *db.DocumentTypes) bool { dest.Data = make([]*db.DocumentTypeData, 2) + dest.Data[0] = &db.DocumentTypeData{Type: "Actor"} d.Actor.ToDB(dest.Data[0]) - dest.Data[0].Type = "Actor" + dest.Data[1] = &db.DocumentTypeData{Type: "Item"} d.Item.ToDB(dest.Data[1]) - dest.Data[1].Type = "Item" return true } diff --git a/internal/foundry/temp_models/json/folder.go b/internal/foundry/temp_models/json/folder.go index b9f7af5..d5f21b1 100644 --- a/internal/foundry/temp_models/json/folder.go +++ b/internal/foundry/temp_models/json/folder.go @@ -20,6 +20,8 @@ func (f *Folder) ToDB(dest **db.Folder) bool { Sorting: f.Sorting, Color: f.Color, } + + folder.Packs = make([]string, len(f.Packs)) copy(folder.Packs, f.Packs) CopySliceToDB(&folder.Folders, f.Folders) @@ -41,20 +43,25 @@ type WorldFolder struct { // Flags any `json:"flags,omitempty"` } -func (w *WorldFolder) ToDB(dest *db.WorldFolder) bool { +func (w *WorldFolder) ToDB(dest **db.WorldFolder) bool { if dest == nil { return false } - dest.Name = w.Name - dest.Type = w.Type - dest.ID = w.ID - dest.Folder = w.Folder - dest.Sorting = w.Sorting - dest.Sort = w.Sort - w.Stats.ToDB(&dest.Stats) - dest.Description = w.Description - dest.Color = w.Color + worldFolder := &db.WorldFolder{ + Name: w.Name, + Type: w.Type, + ID: w.ID, + Folder: w.Folder, + Sorting: w.Sorting, + Sort: w.Sort, + Description: w.Description, + Color: w.Color, + } + + w.Stats.ToDB(&worldFolder.Stats) + + *dest = worldFolder return true } diff --git a/internal/foundry/temp_models/json/game.go b/internal/foundry/temp_models/json/game.go index 8f8de60..c3149b3 100644 --- a/internal/foundry/temp_models/json/game.go +++ b/internal/foundry/temp_models/json/game.go @@ -55,23 +55,25 @@ func (g *Game) ToDB(dest *db.Game) bool { g.Options.ToDB(&dest.Options) g.CoreUpdate.ToDB(&dest.CoreUpdate) g.SystemUpdate.ToDB(&dest.SystemUpdate) + + dest.ActiveUsers = make([]string, len(g.ActiveUsers)) copy(dest.ActiveUsers, g.ActiveUsers) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &dest.Modules, g.Modules) - go CopySliceToDBParallel(&wg, &dest.Packs, g.Packs) - go CopySliceToDBParallel(&wg, &dest.Messages, g.Messages) - go CopySliceToDBParallel(&wg, &dest.Combats, g.Combats) - go CopySliceToDBParallel(&wg, &dest.CardDeck, g.CardDeck) - go CopySliceToDBParallel(&wg, &dest.Users, g.Users) - go CopySliceToDBParallel(&wg, &dest.Macros, g.Macros) - go CopySliceToDBParallel(&wg, &dest.Folders, g.Folders) - go CopySliceToDBParallel(&wg, &dest.Items, g.Items) - go CopySliceToDBParallel(&wg, &dest.Settings, g.Settings) - go CopySliceToDBParallel(&wg, &dest.Journals, g.Journals) - go CopySliceToDBParallel(&wg, &dest.Tables, g.Tables) - go CopySliceToDBParallel(&wg, &dest.Playlists, g.Playlists) - go CopySliceToDBParallel(&wg, &dest.Actors, g.Actors) + CopySliceToDBParallel(&wg, &dest.Modules, g.Modules) + CopySliceToDBParallel(&wg, &dest.Packs, g.Packs) + CopySliceToDBParallel(&wg, &dest.Messages, g.Messages) + CopySliceToDBParallel(&wg, &dest.Combats, g.Combats) + CopySliceToDBParallel(&wg, &dest.CardDeck, g.CardDeck) + CopySliceToDBParallel(&wg, &dest.Users, g.Users) + CopySliceToDBParallel(&wg, &dest.Macros, g.Macros) + CopySliceToDBParallel(&wg, &dest.Folders, g.Folders) + CopySliceToDBParallel(&wg, &dest.Items, g.Items) + CopySliceToDBParallel(&wg, &dest.Settings, g.Settings) + CopySliceToDBParallel(&wg, &dest.Journals, g.Journals) + CopySliceToDBParallel(&wg, &dest.Tables, g.Tables) + CopySliceToDBParallel(&wg, &dest.Playlists, g.Playlists) + CopySliceToDBParallel(&wg, &dest.Actors, g.Actors) // go CopySliceToDBParallel(&wg, &dest.Scenes, g.Scenes) wg.Wait() diff --git a/internal/foundry/temp_models/json/item.go b/internal/foundry/temp_models/json/item.go index 0a4daea..e527e27 100644 --- a/internal/foundry/temp_models/json/item.go +++ b/internal/foundry/temp_models/json/item.go @@ -16,19 +16,23 @@ type Item struct { // Effects []any `json:"effects"` } -func (i *Item) ToDB(dest *db.Item) bool { +func (i *Item) ToDB(dest **db.Item) bool { if dest == nil { return false } - dest.Img = i.Img - dest.Name = i.Name - dest.Type = i.Type - dest.Folder = i.Folder - dest.ID = i.ID - dest.Sort = i.Sort + item := &db.Item{ + Img: i.Img, + Name: i.Name, + Type: i.Type, + Folder: i.Folder, + ID: i.ID, + Sort: i.Sort, + } - i.Stats.ToDB(&dest.Stats) + i.Stats.ToDB(&item.Stats) + + *dest = item return true } diff --git a/internal/foundry/temp_models/json/journal.go b/internal/foundry/temp_models/json/journal.go index 3d69e09..8eaad7b 100644 --- a/internal/foundry/temp_models/json/journal.go +++ b/internal/foundry/temp_models/json/journal.go @@ -14,17 +14,21 @@ type Journal struct { // Categories []any `json:"categories"` } -func (j *Journal) ToDB(dest *db.Journal) bool { +func (j *Journal) ToDB(dest **db.Journal) bool { if dest == nil { return false } - dest.Name = j.Name - dest.Sort = j.Sort - dest.ID = j.ID + journal := &db.Journal{ + Name: j.Name, + Sort: j.Sort, + ID: j.ID, + } - OwnershipToDB(&dest.Ownership, j.Ownership) - CopySliceToDB(&dest.Pages, j.Pages) + OwnershipToDB(&journal.Ownership, j.Ownership) + CopySliceToDB(&journal.Pages, j.Pages) + + *dest = journal return true } diff --git a/internal/foundry/temp_models/json/journal_page.go b/internal/foundry/temp_models/json/journal_page.go index f883943..a9780cd 100644 --- a/internal/foundry/temp_models/json/journal_page.go +++ b/internal/foundry/temp_models/json/journal_page.go @@ -19,23 +19,25 @@ type JournalPage struct { // Category any `json:"category"` } -func (j *JournalPage) ToDB(dest *db.JournalPage) bool { +func (j *JournalPage) ToDB(dest **db.JournalPage) bool { if dest == nil { return false } - dest.Name = j.Name - dest.Type = j.Type - dest.ID = j.ID - dest.Src = j.Src - dest.Sort = j.Sort + journalPage := &db.JournalPage{ + Name: j.Name, + Type: j.Type, + ID: j.ID, + Src: j.Src, + Sort: j.Sort, + } - j.Text.ToDB(&dest.Text) - j.Title.ToDB(&dest.Title) - j.Video.ToDB(&dest.Video) - j.Stats.ToDB(&dest.Stats) + j.Text.ToDB(&journalPage.Text) + j.Title.ToDB(&journalPage.Title) + j.Video.ToDB(&journalPage.Video) + j.Stats.ToDB(&journalPage.Stats) - OwnershipToDB(&dest.Ownership, j.Ownership) + OwnershipToDB(&journalPage.Ownership, j.Ownership) return true } diff --git a/internal/foundry/temp_models/json/macro.go b/internal/foundry/temp_models/json/macro.go index a4f9e1b..b513655 100644 --- a/internal/foundry/temp_models/json/macro.go +++ b/internal/foundry/temp_models/json/macro.go @@ -17,24 +17,28 @@ type Macro struct { // Flags any `json:"flags,omitempty"` } -func (m *Macro) ToDB(dest *db.Macro) bool { +func (m *Macro) ToDB(dest **db.Macro) bool { if dest == nil { return false } - dest.Command = m.Command - dest.Name = m.Name - dest.Type = m.Type - dest.Img = m.Img - dest.ID = m.ID - dest.Author = m.Author - dest.Scope = m.Scope - dest.Folder = m.Folder - dest.Sort = m.Sort + macro := &db.Macro{ + Command: m.Command, + Name: m.Name, + Type: m.Type, + Img: m.Img, + ID: m.ID, + Author: m.Author, + Scope: m.Scope, + Folder: m.Folder, + Sort: m.Sort, + } - m.Stats.ToDB(&dest.Stats) + m.Stats.ToDB(¯o.Stats) - OwnershipToDB(&dest.Ownership, m.Ownership) + OwnershipToDB(¯o.Ownership, m.Ownership) + + *dest = macro return true } diff --git a/internal/foundry/temp_models/json/message.go b/internal/foundry/temp_models/json/message.go index 36921ab..bc0a40c 100644 --- a/internal/foundry/temp_models/json/message.go +++ b/internal/foundry/temp_models/json/message.go @@ -21,27 +21,33 @@ type Message struct { // Flags any `json:"flags"` } -func (m *Message) ToDB(dest *db.Message) bool { +func (m *Message) ToDB(dest **db.Message) bool { if dest == nil { return false } - dest.Content = m.Content - dest.Style = m.Style - dest.Author = m.Author - dest.ID = m.Id - dest.Type = m.Type - dest.Timestamp = m.Timestamp - dest.Flavor = m.Flavor - dest.Blind = m.Blind - dest.Sound = m.Sound - dest.Emote = m.Emote + message := &db.Message{ + Content: m.Content, + Style: m.Style, + Author: m.Author, + ID: m.Id, + Type: m.Type, + Timestamp: m.Timestamp, + Flavor: m.Flavor, + Blind: m.Blind, + Sound: m.Sound, + Emote: m.Emote, + } - m.Speaker.ToDB(&dest.Speaker) - m.Stats.ToDB(&dest.Stats) + m.Speaker.ToDB(&message.Speaker) + m.Stats.ToDB(&message.Stats) - copy(dest.Whisper, m.Whisper) - copy(dest.Rolls, m.Rolls) + message.Whisper = make([]string, len(m.Whisper)) + copy(message.Whisper, m.Whisper) + message.Rolls = make([]string, len(m.Rolls)) + copy(message.Rolls, m.Rolls) + + *dest = message return true } diff --git a/internal/foundry/temp_models/json/module.go b/internal/foundry/temp_models/json/module.go index 6ca62aa..d4ea47a 100644 --- a/internal/foundry/temp_models/json/module.go +++ b/internal/foundry/temp_models/json/module.go @@ -74,8 +74,11 @@ func (m *Module) ToDB(dest **db.Module) bool { Active: m.Active, } + module.Scripts = make([]string, len(m.Scripts)) copy(module.Scripts, m.Scripts) + module.Esmodules = make([]string, len(m.Esmodules)) copy(module.Esmodules, m.Esmodules) + module.Tags = make([]string, len(m.Tags)) copy(module.Tags, m.Tags) m.Compatibility.ToDB(&module.Compatibility) @@ -83,12 +86,12 @@ func (m *Module) ToDB(dest **db.Module) bool { m.DocumentTypes.ToDB(&module.DocumentTypes) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &module.Authors, m.Authors) - go CopySliceToDBParallel(&wg, &module.Media, m.Media) - go CopySliceToDBParallel(&wg, &module.Styles, m.Styles) - go CopySliceToDBParallel(&wg, &module.Languages, m.Languages) - go CopySliceToDBParallel(&wg, &module.Packs, m.Packs) - go CopySliceToDBParallel(&wg, &module.PackFolders, m.PackFolders) + CopySliceToDBParallel(&wg, &module.Authors, m.Authors) + CopySliceToDBParallel(&wg, &module.Media, m.Media) + CopySliceToDBParallel(&wg, &module.Styles, m.Styles) + CopySliceToDBParallel(&wg, &module.Languages, m.Languages) + CopySliceToDBParallel(&wg, &module.Packs, m.Packs) + CopySliceToDBParallel(&wg, &module.PackFolders, m.PackFolders) wg.Wait() *dest = module diff --git a/internal/foundry/temp_models/json/pack.go b/internal/foundry/temp_models/json/pack.go index a74e501..4e26718 100644 --- a/internal/foundry/temp_models/json/pack.go +++ b/internal/foundry/temp_models/json/pack.go @@ -36,14 +36,14 @@ func (p *Pack) ToDB(dest **db.Pack) bool { System: p.System, PackageType: p.PackageType, PackageName: p.PackageName, - ID: p.Id, + Key: p.Id, } p.Ownership.ToDB(&pack.Ownership) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &pack.Index, p.Index) - go CopySliceToDBParallel(&wg, &pack.Folders, p.Folders) + CopySliceToDBParallel(&wg, &pack.Index, p.Index) + CopySliceToDBParallel(&wg, &pack.Folders, p.Folders) wg.Wait() *dest = pack diff --git a/internal/foundry/temp_models/json/package_warnings.go b/internal/foundry/temp_models/json/package_warnings.go index 59ed273..b0548e3 100644 --- a/internal/foundry/temp_models/json/package_warnings.go +++ b/internal/foundry/temp_models/json/package_warnings.go @@ -11,18 +11,25 @@ type PackageWarningsData struct { Manifest string `json:"manifest,omitempty"` } -func (p *PackageWarningsData) ToDB(dest *db.PackageWarningsData) bool { +func (p *PackageWarningsData) ToDB(dest **db.PackageWarningsData) bool { if dest == nil { return false } - dest.ID = p.Id - dest.Type = p.Type - dest.Reinstallable = p.Reinstallable - dest.Manifest = p.Manifest + packageData := &db.PackageWarningsData{ + ID: p.Id, + Type: p.Type, + Reinstallable: p.Reinstallable, + Manifest: p.Manifest, + } - copy(dest.Warning, p.Warning) - copy(dest.Error, p.Error) + packageData.Warning = make([]string, len(p.Warning)) + copy(packageData.Warning, p.Warning) + + packageData.Error = make([]string, len(p.Error)) + copy(packageData.Error, p.Error) + + *dest = packageData return true } diff --git a/internal/foundry/temp_models/json/playlist.go b/internal/foundry/temp_models/json/playlist.go index 913a9fe..08f622b 100644 --- a/internal/foundry/temp_models/json/playlist.go +++ b/internal/foundry/temp_models/json/playlist.go @@ -20,28 +20,30 @@ type Playlist struct { // Flags any `json:"flags,omitempty"` } -func (p *Playlist) ToDB(dest *db.Playlist) bool { +func (p *Playlist) ToDB(dest **db.Playlist) bool { if dest == nil { return false } - dest.Name = p.Name - dest.ID = p.ID - dest.Mode = p.Mode - dest.Playing = p.Playing - dest.Fade = p.Fade - dest.Folder = p.Folder - dest.Sorting = p.Sorting - dest.Seed = p.Seed - dest.Sort = p.Sort - dest.Description = p.Description - dest.Channel = p.Channel + playlist := &db.Playlist{ + Name: p.Name, + ID: p.ID, + Mode: p.Mode, + Playing: p.Playing, + Fade: p.Fade, + Folder: p.Folder, + Sorting: p.Sorting, + Seed: p.Seed, + Sort: p.Sort, + Description: p.Description, + Channel: p.Channel, + } - p.Stats.ToDB(&dest.Stats) + p.Stats.ToDB(&playlist.Stats) - OwnershipToDB(&dest.Ownership, p.Ownership) + OwnershipToDB(&playlist.Ownership, p.Ownership) - CopySliceToDB(&dest.Sounds, p.Sounds) + CopySliceToDB(&playlist.Sounds, p.Sounds) return true } @@ -61,22 +63,26 @@ type Sound struct { // Flags any `json:"flags"` } -func (s *Sound) ToDB(dest *db.Sound) bool { +func (s *Sound) ToDB(dest **db.Sound) bool { if dest == nil { return false } - dest.Name = s.Name - dest.Path = s.Path - dest.ID = s.ID - dest.Playing = s.Playing - dest.PausedTime = s.PausedTime - dest.Repeat = s.Repeat - dest.Volume = s.Volume - dest.Fade = s.Fade - dest.Sort = s.Sort - dest.Channel = s.Channel - dest.Description = s.Description + sound := &db.Sound{ + Name: s.Name, + Path: s.Path, + ID: s.ID, + Playing: s.Playing, + PausedTime: s.PausedTime, + Repeat: s.Repeat, + Volume: s.Volume, + Fade: s.Fade, + Sort: s.Sort, + Channel: s.Channel, + Description: s.Description, + } + + *dest = sound return true } diff --git a/internal/foundry/temp_models/json/relationships.go b/internal/foundry/temp_models/json/relationships.go index e27668c..abc5786 100644 --- a/internal/foundry/temp_models/json/relationships.go +++ b/internal/foundry/temp_models/json/relationships.go @@ -20,10 +20,10 @@ func (r *Relationships) ToDB(dest *db.Relationships) bool { } wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &dest.Systems, r.Systems) - go CopySliceToDBParallel(&wg, &dest.Requires, r.Requires) - go CopySliceToDBParallel(&wg, &dest.Recommends, r.Recommends) - go CopySliceToDBParallel(&wg, &dest.Conflicts, r.Conflicts) + CopySliceToDBParallel(&wg, &dest.Systems, r.Systems) + CopySliceToDBParallel(&wg, &dest.Requires, r.Requires) + CopySliceToDBParallel(&wg, &dest.Recommends, r.Recommends) + CopySliceToDBParallel(&wg, &dest.Conflicts, r.Conflicts) wg.Wait() return true @@ -41,7 +41,7 @@ func (r *RelationshipsData) ToDB(dest *db.RelationshipsData) bool { return false } - dest.ID = r.Id + dest.Key = r.Id dest.Type = r.Type dest.Manifest = r.Manifest diff --git a/internal/foundry/temp_models/json/scene.go b/internal/foundry/temp_models/json/scene.go index 6178cbd..df866fc 100644 --- a/internal/foundry/temp_models/json/scene.go +++ b/internal/foundry/temp_models/json/scene.go @@ -85,12 +85,12 @@ func (s *Scene) ToDB(dest *db.Scene) bool { OwnershipToDB(&dest.Ownership, s.Ownership) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &dest.Drawings, s.Drawings) - go CopySliceToDBParallel(&wg, &dest.Tokens, s.Tokens) - go CopySliceToDBParallel(&wg, &dest.Lights, s.Lights) - go CopySliceToDBParallel(&wg, &dest.Notes, s.Notes) - go CopySliceToDBParallel(&wg, &dest.Sounds, s.Sounds) - go CopySliceToDBParallel(&wg, &dest.Walls, s.Walls) + CopySliceToDBParallel(&wg, &dest.Drawings, s.Drawings) + CopySliceToDBParallel(&wg, &dest.Tokens, s.Tokens) + CopySliceToDBParallel(&wg, &dest.Lights, s.Lights) + CopySliceToDBParallel(&wg, &dest.Notes, s.Notes) + CopySliceToDBParallel(&wg, &dest.Sounds, s.Sounds) + CopySliceToDBParallel(&wg, &dest.Walls, s.Walls) wg.Wait() return true diff --git a/internal/foundry/temp_models/json/settings.go b/internal/foundry/temp_models/json/settings.go index 5951d29..ae972fb 100644 --- a/internal/foundry/temp_models/json/settings.go +++ b/internal/foundry/temp_models/json/settings.go @@ -10,15 +10,20 @@ type Setting struct { Stats Stats `json:"_stats"` } -func (s *Setting) ToDB(dest *db.Setting) bool { +func (s *Setting) ToDB(dest **db.Setting) bool { if dest == nil { return false } - dest.Key = s.Key - dest.Value = s.Value - dest.ID = s.ID - s.Stats.ToDB(&dest.Stats) + setting := &db.Setting{ + Key: s.Key, + Value: s.Value, + ID: s.ID, + } + + s.Stats.ToDB(&setting.Stats) + + *dest = setting return true } diff --git a/internal/foundry/temp_models/json/setup.go b/internal/foundry/temp_models/json/setup.go index 9e8ef26..01dda9f 100644 --- a/internal/foundry/temp_models/json/setup.go +++ b/internal/foundry/temp_models/json/setup.go @@ -1,6 +1,7 @@ package json import ( + "encoding/json" "sync" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" @@ -22,6 +23,19 @@ type Setup struct { Worlds []*World `json:"worlds"` } +func ParseSetup(data []byte) (*Setup, error) { + var modelSetup []Setup + err := json.Unmarshal(data, &modelSetup) + if err != nil { + return nil, err + } + + if len(modelSetup) > 1 { + return nil, ErrorSetupMoreThanOne + } + return &modelSetup[0], nil +} + func (s *Setup) ToDB(dest *db.Setup) bool { if dest == nil { return false @@ -39,11 +53,11 @@ func (s *Setup) ToDB(dest *db.Setup) bool { PackageWarningsToDB(&dest.PackageWarnings, s.PackageWarnings) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &dest.Languages, s.Languages) - go CopySliceToDBParallel(&wg, &dest.Modules, s.Modules) - go CopySliceToDBParallel(&wg, &dest.News, s.News) - go CopySliceToDBParallel(&wg, &dest.Systems, s.Systems) - go CopySliceToDBParallel(&wg, &dest.Worlds, s.Worlds) + CopySliceToDBParallel(&wg, &dest.Languages, s.Languages) + CopySliceToDBParallel(&wg, &dest.Modules, s.Modules) + CopySliceToDBParallel(&wg, &dest.News, s.News) + CopySliceToDBParallel(&wg, &dest.Systems, s.Systems) + CopySliceToDBParallel(&wg, &dest.Worlds, s.Worlds) wg.Wait() return true diff --git a/internal/foundry/temp_models/json/system.go b/internal/foundry/temp_models/json/system.go index 83884be..1f47aa6 100644 --- a/internal/foundry/temp_models/json/system.go +++ b/internal/foundry/temp_models/json/system.go @@ -71,8 +71,11 @@ func (s *System) ToDB(dest **db.System) bool { HasStorage: s.HasStorage, } + system.Scripts = make([]string, len(s.Scripts)) copy(system.Scripts, s.Scripts) + system.Esmodules = make([]string, len(s.Esmodules)) copy(system.Esmodules, s.Esmodules) + system.Tags = make([]string, len(s.Tags)) copy(system.Tags, s.Tags) s.Compatibility.ToDB(&system.Compatibility) @@ -81,12 +84,12 @@ func (s *System) ToDB(dest **db.System) bool { s.Grid.ToDB(&system.Grid) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &system.Authors, s.Authors) - go CopySliceToDBParallel(&wg, &system.Media, s.Media) - go CopySliceToDBParallel(&wg, &system.Styles, s.Styles) - go CopySliceToDBParallel(&wg, &system.Languages, s.Languages) - go CopySliceToDBParallel(&wg, &system.Packs, s.Packs) - go CopySliceToDBParallel(&wg, &system.PackFolders, s.PackFolders) + CopySliceToDBParallel(&wg, &system.Authors, s.Authors) + CopySliceToDBParallel(&wg, &system.Media, s.Media) + CopySliceToDBParallel(&wg, &system.Styles, s.Styles) + CopySliceToDBParallel(&wg, &system.Languages, s.Languages) + CopySliceToDBParallel(&wg, &system.Packs, s.Packs) + CopySliceToDBParallel(&wg, &system.PackFolders, s.PackFolders) wg.Wait() *dest = system diff --git a/internal/foundry/temp_models/json/table.go b/internal/foundry/temp_models/json/table.go index cf8f660..94b3943 100644 --- a/internal/foundry/temp_models/json/table.go +++ b/internal/foundry/temp_models/json/table.go @@ -18,26 +18,28 @@ type Table struct { // TablesFlags any `json:"flags,omitempty"` } -func (t *Table) ToDB(dest *db.Table) bool { +func (t *Table) ToDB(dest **db.Table) bool { if dest == nil { return false } - dest.Name = t.Name - dest.Description = t.Description - dest.Formula = t.Formula - dest.ID = t.ID - dest.Img = t.Img - dest.Replacement = t.Replacement - dest.DisplayRoll = t.DisplayRoll - dest.Folder = t.Folder - dest.Sort = t.Sort + table := &db.Table{ + Name: t.Name, + Description: t.Description, + Formula: t.Formula, + ID: t.ID, + Img: t.Img, + Replacement: t.Replacement, + DisplayRoll: t.DisplayRoll, + Folder: t.Folder, + Sort: t.Sort, + } - t.Stats.ToDB(&dest.Stats) + t.Stats.ToDB(&table.Stats) - OwnershipToDB(&dest.Ownership, t.Ownership) + OwnershipToDB(&table.Ownership, t.Ownership) - CopySliceToDB(&dest.Results, t.Results) + CopySliceToDB(&table.Results, t.Results) return true } @@ -55,22 +57,27 @@ type TableResult struct { // ResultsFlags any `json:"flags"` } -func (t *TableResult) ToDB(dest *db.TableResult) bool { +func (t *TableResult) ToDB(dest **db.TableResult) bool { if dest == nil { return false } - dest.Type = t.Type - dest.Weight = t.Weight - dest.Drawn = t.Drawn - dest.ID = t.ID - dest.Img = t.Img - dest.Description = t.Description - dest.Name = t.Name + tableResult := &db.TableResult{ + Type: t.Type, + Weight: t.Weight, + Drawn: t.Drawn, + ID: t.ID, + Img: t.Img, + Description: t.Description, + Name: t.Name, + } - copy(dest.Range, t.Range) + tableResult.Range = make([]int, len(t.Range)) + copy(tableResult.Range, t.Range) - t.Stats.ToDB(&dest.Stats) + t.Stats.ToDB(&tableResult.Stats) + + *dest = tableResult return true } diff --git a/internal/foundry/temp_models/json/user.go b/internal/foundry/temp_models/json/user.go index bf26327..e4e785c 100644 --- a/internal/foundry/temp_models/json/user.go +++ b/internal/foundry/temp_models/json/user.go @@ -16,22 +16,26 @@ type User struct { // UsersFlags any `json:"flags,omitempty"` } -func (u *User) ToDB(dest *db.User) bool { +func (u *User) ToDB(dest **db.User) bool { if dest == nil { return false } - dest.Name = u.Name - dest.Role = u.Role - dest.ID = u.ID - dest.Avatar = u.Avatar - dest.Character = u.Character - dest.Color = u.Color - dest.Pronouns = u.Pronouns + user := &db.User{ + Name: u.Name, + Role: u.Role, + ID: u.ID, + Avatar: u.Avatar, + Character: u.Character, + Color: u.Color, + Pronouns: u.Pronouns, + } - u.UsersStats.ToDB(&dest.Stats) + u.UsersStats.ToDB(&user.Stats) - HotbarToDB(&dest.Hotbar, u.Hotbar) + HotbarToDB(&user.Hotbar, u.Hotbar) + + *dest = user return true } diff --git a/internal/foundry/temp_models/json/utils.go b/internal/foundry/temp_models/json/utils.go index 8480d8e..4356980 100644 --- a/internal/foundry/temp_models/json/utils.go +++ b/internal/foundry/temp_models/json/utils.go @@ -1,11 +1,16 @@ package json import ( + "errors" "sync" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" ) +var ( + ErrorSetupMoreThanOne = errors.New("More than one setup data") +) + func OwnershipToDB(dest *[]db.OwnershipString, src map[string]int) { *dest = make([]db.OwnershipString, len(src)) @@ -33,8 +38,8 @@ func PackageWarningsToDB(dest *[]*db.PackageWarning, src map[string]PackageWarni i := 0 for k, v := range src { - (*dest)[i].Key = k - v.ToDB((*dest)[i].Value) + (*dest)[i] = &db.PackageWarning{Key: k} + v.ToDB(&(*dest)[i].Value) i++ } } @@ -57,7 +62,7 @@ func CopySliceToDB[destType any, srcType CastableToDB[destType]](dest *[]destTyp } func CopySliceToDBParallel[destType any, srcType CastableToDB[destType]](wg *sync.WaitGroup, dest *[]destType, src []srcType) { - wg.Add(1) - CopySliceToDB(dest, src) - wg.Done() + wg.Go(func() { + CopySliceToDB(dest, src) + }) } diff --git a/internal/foundry/temp_models/json/wall.go b/internal/foundry/temp_models/json/wall.go index ac60e9e..596c1f8 100644 --- a/internal/foundry/temp_models/json/wall.go +++ b/internal/foundry/temp_models/json/wall.go @@ -32,6 +32,7 @@ func (w *Wall) ToDB(dest *db.Wall) bool { dest.ID = w.ID w.Threshold.ToDB(&dest.Threshold) + dest.C = make([]int, len(w.C)) copy(dest.C, w.C) return true diff --git a/internal/foundry/temp_models/json/world.go b/internal/foundry/temp_models/json/world.go index 0166076..cb46e01 100644 --- a/internal/foundry/temp_models/json/world.go +++ b/internal/foundry/temp_models/json/world.go @@ -71,20 +71,23 @@ func (w *World) ToDB(dest **db.World) bool { HasStorage: w.HasStorage, } + world.Scripts = make([]string, len(w.Scripts)) copy(world.Scripts, w.Scripts) + world.Esmodules = make([]string, len(w.Esmodules)) copy(world.Esmodules, w.Esmodules) + world.Tags = make([]string, len(w.Tags)) copy(world.Tags, w.Tags) w.Compatibility.ToDB(&world.Compatibility) w.Relationships.ToDB(&world.Relationships) wg := sync.WaitGroup{} - go CopySliceToDBParallel(&wg, &world.Authors, w.Authors) - go CopySliceToDBParallel(&wg, &world.Media, w.Media) - go CopySliceToDBParallel(&wg, &world.Styles, w.Styles) - go CopySliceToDBParallel(&wg, &world.Languages, w.Languages) - go CopySliceToDBParallel(&wg, &world.Packs, w.Packs) - go CopySliceToDBParallel(&wg, &world.PackFolders, w.PackFolders) + CopySliceToDBParallel(&wg, &world.Authors, w.Authors) + CopySliceToDBParallel(&wg, &world.Media, w.Media) + CopySliceToDBParallel(&wg, &world.Styles, w.Styles) + CopySliceToDBParallel(&wg, &world.Languages, w.Languages) + CopySliceToDBParallel(&wg, &world.Packs, w.Packs) + CopySliceToDBParallel(&wg, &world.PackFolders, w.PackFolders) wg.Wait() *dest = world diff --git a/internal/foundry/transport/db.go b/internal/foundry/transport/db.go index b215dc6..6897489 100644 --- a/internal/foundry/transport/db.go +++ b/internal/foundry/transport/db.go @@ -1,9 +1,9 @@ package transport import ( - "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/db" - "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/json" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" + "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" + "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/json" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" ) @@ -14,22 +14,22 @@ func (tr *FoundryTransport) FillDBWithFoundryData() { return } - idState, err := tr.Models.FoundryState.GetIdByType(db.SetupState) - if err != nil { - tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} - return - } + // idState, err := tr.Models.FoundryState.GetIdByType(db.SetupState) + // if err != nil { + // tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} + // return + // } - err = tr.InitWorldsData(idState) - if err != nil { - tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} - return - } + // err = tr.InitWorldsData(idState) + // if err != nil { + // tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} + // return + // } } func (tr *FoundryTransport) InitSetupData() error { - tr.Models.FoundryState.DeleteAll() - tr.Models.FoundryState.DeleteAllSeq() + db.DeleteAll(tr.DB) + db.DeleteAllSeq(tr.DB) for k := range requests.PathToSetupState { err := tr.InsertJsonDataToDB(k) if err != nil { @@ -51,48 +51,51 @@ func (tr *FoundryTransport) InsertJsonDataToDB(statePath string) error { return err } - foundryStateJson, err := json.ParseSetupModel(msgJson) + foundryStateJson, err := json.ParseSetup(msgJson) if err != nil { return err } - foundryStateDb := foundryStateJson.GetFoundryStateDB(requests.PathToSetupState[statePath]) - err = tr.Models.FoundryState.Insert(foundryStateDb) + tr.Logger.Info("Setup data received") + + var foundryStateDb db.Setup + foundryStateJson.ToDB(&foundryStateDb) + err = foundryStateDb.Insert(tr.DB) if err != nil { return err } return nil } -func (tr *FoundryTransport) InitWorldsData(idState int64) error { - worlds, err := tr.Models.FoundryState.GetWorlds(idState) - if err != nil { - return err - } - tr.Logger.Debug("Worlds", "len", len(worlds)) +// func (tr *FoundryTransport) InitWorldsData(idState int64) error { +// worlds, err := tr.Models.FoundryState.GetWorlds(idState) +// if err != nil { +// return err +// } +// tr.Logger.Debug("Worlds", "len", len(worlds)) - for i := range worlds { - worldName := worlds[i].TextId - tr.InitWorldData(worldName) - _, err = tr.Http.PostReturnToSetup() - if err != nil { - return err - } - } - return nil -} +// for i := range worlds { +// worldName := worlds[i].TextId +// tr.InitWorldData(worldName) +// _, err = tr.Http.PostReturnToSetup() +// if err != nil { +// return err +// } +// } +// return nil +// } -func (tr *FoundryTransport) InitWorldData(worldName string) error { - tr.Logger.Debug("World name", "name", worldName) - err := tr.LaunchWorld(worldName) - if err != nil { - return err - } - for k := range requests.PathToWorldState { - err := tr.InsertJsonDataToDB(k) - if err != nil { - return err - } - } - return nil -} +// func (tr *FoundryTransport) InitWorldData(worldName string) error { +// tr.Logger.Debug("World name", "name", worldName) +// err := tr.LaunchWorld(worldName) +// if err != nil { +// return err +// } +// for k := range requests.PathToWorldState { +// err := tr.InsertJsonDataToDB(k) +// if err != nil { +// return err +// } +// } +// return nil +// } diff --git a/internal/foundry/transport/transport.go b/internal/foundry/transport/transport.go index 6a8b09d..4c637e4 100644 --- a/internal/foundry/transport/transport.go +++ b/internal/foundry/transport/transport.go @@ -5,7 +5,6 @@ import ( "sync" "time" - "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/db" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "github.com/gorilla/websocket" @@ -26,7 +25,8 @@ type FoundryTransport struct { IsAuth bool IsLogin bool - Models *db.Models + // Models *db.Models + DB *sqlx.DB IsDbInit bool Logger *slog.Logger @@ -47,7 +47,7 @@ func NewFoundryTransport(dbConn *sqlx.DB, logger *slog.Logger, httpConfig *reque ReconnectNumMax: 1, ReconnectNum: 0, - Models: db.NewModels(dbConn), + DB: dbConn, IsDbInit: false, Logger: logger,