finish setup data insertion, add world insertion
This commit is contained in:
@@ -7,6 +7,10 @@ DROP TABLE IF EXISTS author;
|
|||||||
DROP TABLE IF EXISTS es_modules;
|
DROP TABLE IF EXISTS es_modules;
|
||||||
DROP TABLE IF EXISTS scripts;
|
DROP TABLE IF EXISTS scripts;
|
||||||
DROP TABLE IF EXISTS tags;
|
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 relationships;
|
||||||
DROP TABLE IF EXISTS compatibility;
|
DROP TABLE IF EXISTS compatibility;
|
||||||
DROP TABLE IF EXISTS world;
|
DROP TABLE IF EXISTS world;
|
||||||
|
|||||||
@@ -171,9 +171,9 @@ CREATE TABLE IF NOT EXISTS relationships (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS relationships_systems (
|
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,
|
type TEXT NOT NULL,
|
||||||
manifest 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 (
|
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,
|
type TEXT NOT NULL,
|
||||||
manifest 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 (
|
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,
|
type TEXT NOT NULL,
|
||||||
manifest 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 (
|
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,
|
type TEXT NOT NULL,
|
||||||
manifest TEXT NOT NULL,
|
manifest TEXT NOT NULL,
|
||||||
|
|
||||||
@@ -222,17 +222,14 @@ CREATE TABLE IF NOT EXISTS compatibility (
|
|||||||
maximum VARCHAR(64) NOT NULL,
|
maximum VARCHAR(64) NOT NULL,
|
||||||
|
|
||||||
module_id TEXT UNIQUE,
|
module_id TEXT UNIQUE,
|
||||||
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
|
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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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 (
|
CREATE TABLE IF NOT EXISTS scripts (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
@@ -304,8 +301,9 @@ CREATE TABLE IF NOT EXISTS language (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS pack (
|
CREATE TABLE IF NOT EXISTS pack (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
|
|
||||||
|
key_ VARCHAR(128) NOT NULL,
|
||||||
name VARCHAR(128) NOT NULL,
|
name VARCHAR(128) NOT NULL,
|
||||||
label VARCHAR(128) NOT NULL,
|
label VARCHAR(128) NOT NULL,
|
||||||
banner VARCHAR(128) NOT NULL,
|
banner VARCHAR(128) NOT NULL,
|
||||||
@@ -326,7 +324,7 @@ CREATE TABLE IF NOT EXISTS ownership (
|
|||||||
trusted VARCHAR(128) NOT NULL,
|
trusted VARCHAR(128) NOT NULL,
|
||||||
assistant 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
|
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,
|
name VARCHAR(128) NOT NULL,
|
||||||
type 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
|
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,
|
type VARCHAR(128) NOT NULL,
|
||||||
sort INTEGER NOT NULL,
|
sort INTEGER NOT NULL,
|
||||||
|
|
||||||
pack_id TEXT,
|
pack_id INTEGER,
|
||||||
FOREIGN KEY (pack_id) REFERENCES pack(id) ON DELETE CASCADE
|
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,
|
color VARCHAR(128) NOT NULL,
|
||||||
|
|
||||||
folder_id INTEGER,
|
folder_id INTEGER,
|
||||||
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE,
|
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE
|
||||||
module_id TEXT,
|
|
||||||
FOREIGN KEY (module_id) REFERENCES module(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 (
|
CREATE TABLE IF NOT EXISTS folder_packs (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
packs VARCHAR(128) NOT NULL,
|
value VARCHAR(128) NOT NULL,
|
||||||
|
|
||||||
folder_id INTEGER,
|
folder_id INTEGER,
|
||||||
FOREIGN KEY (folder_id) REFERENCES folder(id) ON DELETE CASCADE
|
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 (
|
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,
|
setup_id INTEGER,
|
||||||
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
|
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,
|
manifest VARCHAR(128) NOT NULL,
|
||||||
reinstallable BOOLEAN 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
|
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
|
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
ALTER TABLE compatibility ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id);
|
ALTER TABLE compatibility ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE;
|
||||||
ALTER TABLE relationships ADD COLUMN system_id TEXT UNIQUE REFERENCES system(id);
|
CREATE UNIQUE INDEX idx_compatibility_system_id ON compatibility(system_id);
|
||||||
ALTER TABLE document_types ADD COLUMN system_id TEXT UNIQUE REFERENCES 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 (
|
CREATE TABLE IF NOT EXISTS grid (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
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
|
FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
ALTER TABLE es_modules 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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
ALTER TABLE folder ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS world (
|
CREATE TABLE IF NOT EXISTS world (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
@@ -512,15 +514,17 @@ CREATE TABLE IF NOT EXISTS world (
|
|||||||
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
|
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
ALTER TABLE compatibility ADD COLUMN world_id TEXT UNIQUE REFERENCES world(id);
|
ALTER TABLE compatibility ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE;
|
||||||
ALTER TABLE relationships ADD COLUMN world_id TEXT UNIQUE REFERENCES world(id);
|
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 tags ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE;
|
||||||
ALTER TABLE scripts ADD COLUMN world_id TEXT REFERENCES world(id);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
ALTER TABLE folder ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE;
|
||||||
|
|||||||
@@ -361,10 +361,6 @@ CREATE TABLE IF NOT EXISTS active_users (
|
|||||||
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
|
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS item (
|
CREATE TABLE IF NOT EXISTS item (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
|
|
||||||
@@ -473,7 +469,7 @@ CREATE TABLE IF NOT EXISTS combatant (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS stats (
|
CREATE TABLE IF NOT EXISTS stats (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
core_version VARCHAR(128) NOT NULL,
|
core_version VARCHAR(128) NOT NULL,
|
||||||
system_id 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 (
|
CREATE TABLE IF NOT EXISTS speaker (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
scene VARCHAR(128) NOT NULL,
|
scene VARCHAR(128) NOT NULL,
|
||||||
actor 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 (
|
CREATE TABLE IF NOT EXISTS message_whisper (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
|
|
||||||
whisper VARCHAR(128) NOT NULL,
|
value VARCHAR(128) NOT NULL,
|
||||||
|
|
||||||
message_id TEXT,
|
message_id TEXT,
|
||||||
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
|
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 (
|
CREATE TABLE IF NOT EXISTS message_rolls (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
|
|
||||||
rolls VARCHAR(128) NOT NULL,
|
value VARCHAR(128) NOT NULL,
|
||||||
|
|
||||||
message_id TEXT,
|
message_id TEXT,
|
||||||
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
|
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
|
FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS system_update (
|
CREATE TABLE IF NOT EXISTS system_update (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ type Actor struct {
|
|||||||
Sort int
|
Sort int
|
||||||
PrototypeToken Token
|
PrototypeToken Token
|
||||||
Stats Stats
|
Stats Stats
|
||||||
Items []Item
|
Items []*Item
|
||||||
Ownership []OwnershipString
|
Ownership []OwnershipString
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
type Addresses struct {
|
type Addresses struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
@@ -7,3 +13,40 @@ type Addresses struct {
|
|||||||
Remote string
|
Remote string
|
||||||
RemoteIsAccessible bool
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type CardDeck struct {
|
type CardDeck struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -15,7 +24,58 @@ type CardDeck struct {
|
|||||||
DisplayCount bool
|
DisplayCount bool
|
||||||
Stats Stats
|
Stats Stats
|
||||||
Ownership Ownership
|
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 {
|
type Card struct {
|
||||||
@@ -38,6 +98,57 @@ type Card struct {
|
|||||||
Faces []Face
|
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 {
|
type Face struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
@@ -46,9 +157,83 @@ type Face struct {
|
|||||||
Text string
|
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 {
|
type Back struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
Name string
|
Name string
|
||||||
Text 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Combat struct {
|
type Combat struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -11,9 +20,58 @@ type Combat struct {
|
|||||||
Active bool
|
Active bool
|
||||||
Stats Stats
|
Stats Stats
|
||||||
Groups []string
|
Groups []string
|
||||||
Combatants []Combatant
|
Combatants []*Combatant
|
||||||
// System any `json:"system"`
|
}
|
||||||
// Flags any `json:"flags"`
|
|
||||||
|
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 {
|
type Combatant struct {
|
||||||
@@ -29,6 +87,53 @@ type Combatant struct {
|
|||||||
Hidden bool
|
Hidden bool
|
||||||
Defeated bool
|
Defeated bool
|
||||||
Stats Stats
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DocumentTypes struct {
|
type DocumentTypes struct {
|
||||||
@@ -13,10 +17,10 @@ type DocumentTypes struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d DocumentTypes) Query(data *InsertId[string]) {
|
func (d DocumentTypes) Query(data *InsertId[string]) {
|
||||||
data.query = `
|
data.query = fmt.Sprintf(`
|
||||||
INSERT INTO document_types (module_id)
|
INSERT INTO document_types (%s)
|
||||||
VALUES ($1)
|
VALUES ($1)
|
||||||
RETURNING id`
|
RETURNING id`, data.fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DocumentTypes) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
InsertSliceParallel(group, tx, d.Data, InsertId[uint]{id: d.ID})
|
||||||
InsertSliceParallel(syncDB, 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 {
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
InsertSliceParallel(group, tx, d.Data, InsertId[uint]{id: d.ID})
|
||||||
InsertSliceParallel(syncDB, 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 {
|
type DocumentTypeData struct {
|
||||||
@@ -78,17 +88,16 @@ func (d *DocumentTypeData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
|
|||||||
|
|
||||||
args := []any{data.id, d.Type}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
relData := &InsertId[uint]{id: d.ID, fieldName: "document_types_data_id", tableName: "document_types_data_html"}
|
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 {
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
relData := &InsertId[uint]{id: d.ID, fieldName: "document_types_data_id", tableName: "document_types_data_html"}
|
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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Files struct {
|
type Files struct {
|
||||||
@@ -32,12 +35,15 @@ func (f *Files) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
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 {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
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 {
|
type FilesStorage struct {
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
@@ -26,18 +29,21 @@ func (f *Folder) Query(data *InsertId[string]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Folder) InsertObjects(tx *sqlx.Tx) error {
|
func (f *Folder) InsertObjects(tx *sqlx.Tx) error {
|
||||||
relId := &InsertId[string]{
|
relId := InsertId[string]{
|
||||||
id: strconv.FormatUint(uint64(f.ID), 10),
|
id: strconv.FormatUint(uint64(f.ID), 10),
|
||||||
fieldName: "folder_id",
|
fieldName: "folder_id",
|
||||||
tableName: "folder_packs",
|
tableName: "folder_packs",
|
||||||
}
|
}
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertSimpleSliceParallel(syncDB, tx, f.Packs, relId)
|
InsertSimpleSliceParallel(group, tx, f.Packs, &relId)
|
||||||
InsertSliceParallel(syncDB, tx, f.Folders, 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 {
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -81,5 +87,54 @@ type WorldFolder struct {
|
|||||||
Color string
|
Color string
|
||||||
Sort int
|
Sort int
|
||||||
Stats Stats
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,25 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
type Game struct {
|
import (
|
||||||
ID uint
|
"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
|
Addresses Addresses
|
||||||
Files Files
|
Files Files
|
||||||
Options GameOptions
|
Options GameOptions
|
||||||
@@ -19,17 +32,83 @@ type Game struct {
|
|||||||
Modules []*Module
|
Modules []*Module
|
||||||
PackageWarnings []*PackageWarning
|
PackageWarnings []*PackageWarning
|
||||||
Packs []*Pack
|
Packs []*Pack
|
||||||
Messages []Message
|
Messages []*Message
|
||||||
Combats []Combat
|
Combats []*Combat
|
||||||
CardDeck []CardDeck
|
CardDeck []*CardDeck
|
||||||
Users []User
|
Users []*User
|
||||||
Macros []Macro
|
Macros []*Macro
|
||||||
Folders []WorldFolder
|
Folders []*WorldFolder
|
||||||
Items []Item
|
Items []*Item
|
||||||
Settings []Setting
|
Settings []*Setting
|
||||||
Journals []Journal
|
Journals []*Journal
|
||||||
Tables []Table
|
Tables []*Table //
|
||||||
Playlists []Playlist
|
Playlists []*Playlist
|
||||||
Actors []Actor //
|
Actors []Actor //
|
||||||
// Scenes []Scene
|
// 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()
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type Grid struct {
|
|||||||
|
|
||||||
func (g *Grid) Query(data *InsertId[string]) {
|
func (g *Grid) Query(data *InsertId[string]) {
|
||||||
data.query = `
|
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)
|
alpha, color, units, style)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||||
RETURNING id`
|
RETURNING id`
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ type Index struct {
|
|||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Index) Query(data *InsertId[string]) {
|
func (i *Index) Query(data *InsertId[uint]) {
|
||||||
data.query = `
|
data.query = `
|
||||||
INSERT INTO index_ (pack_id, id, folder, img, name, type)
|
INSERT INTO index_ (pack_id, id, folder, img, name, type)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6)
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
RETURNING id`
|
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 == "" {
|
if data.query == "" {
|
||||||
return ErrNoQuery
|
return ErrNoQuery
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
|||||||
return nil
|
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 == "" {
|
if data.query == "" {
|
||||||
return ErrNoQuery
|
return ErrNoQuery
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -11,3 +21,54 @@ type Item struct {
|
|||||||
Stats Stats
|
Stats Stats
|
||||||
Ownership []OwnershipString
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,70 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Journal struct {
|
type Journal struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
Name string
|
Name string
|
||||||
Sort int
|
Sort int
|
||||||
Pages []JournalPage
|
Pages []*JournalPage
|
||||||
Ownership []OwnershipString
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type JournalPage struct {
|
type JournalPage struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -14,6 +24,60 @@ type JournalPage struct {
|
|||||||
Ownership []OwnershipString
|
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 {
|
type PageText struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
@@ -22,6 +86,42 @@ type PageText struct {
|
|||||||
Format int
|
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 {
|
type PageTitle struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
@@ -29,9 +129,81 @@ type PageTitle struct {
|
|||||||
Level int
|
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 {
|
type PageVideo struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
Controls bool
|
Controls bool
|
||||||
Volume float64
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SetupLanguage struct {
|
type SetupLanguage struct {
|
||||||
@@ -33,11 +36,10 @@ func (l *SetupLanguage) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
InsertSliceParallel(group, tx, l.Modules, InsertId[string]{id: l.ID})
|
||||||
InsertSliceParallel(syncDB, 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 {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
InsertSliceParallel(group, tx, l.Modules, InsertId[string]{id: l.ID})
|
||||||
InsertSliceParallel(syncDB, tx, l.Modules, &InsertId[string]{id: l.ID})
|
|
||||||
|
|
||||||
|
err = group.Wait()
|
||||||
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Macro struct {
|
type Macro struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -14,3 +23,53 @@ type Macro struct {
|
|||||||
Stats Stats
|
Stats Stats
|
||||||
Ownership []OwnershipString
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -18,6 +28,59 @@ type Message struct {
|
|||||||
Rolls []string
|
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 {
|
type Speaker struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
@@ -26,3 +89,39 @@ type Speaker struct {
|
|||||||
Token string
|
Token string
|
||||||
Alias 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Module struct {
|
type Module struct {
|
||||||
@@ -55,29 +58,32 @@ func (m *Module) Query(data *InsertId[uint]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) InsertObjects(tx *sqlx.Tx) error {
|
func (m *Module) InsertObjects(tx *sqlx.Tx) error {
|
||||||
relId := &InsertId[string]{id: m.ID, fieldName: "module_id"}
|
relId := InsertId[string]{id: m.ID, fieldName: "module_id"}
|
||||||
syncDB := NewSyncDB()
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
go InsertWithCtxParallel(syncDB, tx, m.DocumentTypes, relId)
|
InsertWithCtxParallel(group, ctx, tx, m.DocumentTypes, relId)
|
||||||
go InsertWithCtxParallel(syncDB, tx, m.Relationships, relId)
|
InsertWithCtxParallel(group, ctx, tx, m.Relationships, relId)
|
||||||
go InsertWithCtxParallel(syncDB, tx, m.Compatibility, relId)
|
InsertWithCtxParallel(group, ctx, tx, m.Compatibility, relId)
|
||||||
|
|
||||||
scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"}
|
// scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"}
|
||||||
go InsertSimpleSliceParallel(syncDB, tx, m.Scripts, scriptRelId)
|
// InsertSimpleSliceParallel(group, tx, m.Scripts, scriptRelId)
|
||||||
esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"}
|
// esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"}
|
||||||
go InsertSimpleSliceParallel(syncDB, tx, m.Esmodules, esModulesRelId)
|
// InsertSimpleSliceParallel(group, tx, m.Esmodules, esModulesRelId)
|
||||||
tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"}
|
// tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"}
|
||||||
go InsertSimpleSliceParallel(syncDB, tx, m.Tags, tagsRelId)
|
// InsertSimpleSliceParallel(group, tx, m.Tags, tagsRelId)
|
||||||
|
|
||||||
go InsertSliceParallel(syncDB, tx, m.Authors, relId)
|
// InsertSliceParallel(group, tx, m.Authors, relId)
|
||||||
go InsertSliceParallel(syncDB, tx, m.Media, relId)
|
// InsertSliceParallel(group, tx, m.Media, relId)
|
||||||
go InsertSliceParallel(syncDB, tx, m.Styles, relId)
|
// InsertSliceParallel(group, tx, m.Styles, relId)
|
||||||
go InsertSliceParallel(syncDB, tx, m.Languages, relId)
|
// InsertSliceParallel(group, tx, m.Languages, relId)
|
||||||
go InsertSliceParallel(syncDB, tx, m.Packs, relId)
|
// InsertSliceParallel(group, tx, m.Packs, relId)
|
||||||
go InsertSliceParallel(syncDB, tx, m.PackFolders, 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 {
|
func (m *Module) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
|
||||||
|
|||||||
@@ -14,15 +14,21 @@ type GameOptions struct {
|
|||||||
Port int
|
Port int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameOptions) Insert(tx *sqlx.Tx, gameId *InsertId[uint]) error {
|
func (g *GameOptions) Query(data *InsertId[uint]) {
|
||||||
query := `
|
data.query = `
|
||||||
INSERT INTO featured_content (game_id, language, update_channel, port)
|
INSERT INTO featured_content (game_id, language, update_channel, port)
|
||||||
VALUES ($1, $2, $3, $4)
|
VALUES ($1, $2, $3, $4)
|
||||||
RETURNING id`
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -30,15 +36,14 @@ func (g *GameOptions) Insert(tx *sqlx.Tx, gameId *InsertId[uint]) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, gameId *InsertId[uint]) error {
|
func (g *GameOptions) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
|
||||||
query := `
|
if data.query == "" {
|
||||||
INSERT INTO featured_content (game_id, language, update_channel, port)
|
return ErrNoQuery
|
||||||
VALUES ($1, $2, $3, $4)
|
}
|
||||||
RETURNING id`
|
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -71,7 +76,7 @@ func (s *SetupOptions) Query(data *InsertId[uint]) {
|
|||||||
data.query = `
|
data.query = `
|
||||||
INSERT INTO setup_options (setup_id, css_theme, data_path, hostname, language, local_hostname,
|
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,
|
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)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
|
||||||
RETURNING id`
|
RETURNING id`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
@@ -15,10 +16,10 @@ type Ownership struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o Ownership) Query(data *InsertId[string]) {
|
func (o Ownership) Query(data *InsertId[string]) {
|
||||||
data.query = `
|
data.query = fmt.Sprintf(`
|
||||||
INSERT INTO ownership (%s, player, trusted, assistant)
|
INSERT INTO ownership (%s, player, trusted, assistant)
|
||||||
VALUES ($1, $2, $3, $4)
|
VALUES ($1, $2, $3, $4)
|
||||||
RETURNING id`
|
RETURNING id`, data.fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Ownership) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -57,3 +58,40 @@ type OwnershipString struct {
|
|||||||
Key string
|
Key string
|
||||||
Value int
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,14 +2,19 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pack struct {
|
type Pack struct {
|
||||||
ID string
|
ID uint
|
||||||
|
|
||||||
|
Key string
|
||||||
Name string
|
Name string
|
||||||
Label string
|
Label string
|
||||||
Banner string
|
Banner string
|
||||||
@@ -25,21 +30,26 @@ type Pack struct {
|
|||||||
|
|
||||||
func (p *Pack) Query(data *InsertId[string]) {
|
func (p *Pack) Query(data *InsertId[string]) {
|
||||||
data.query = fmt.Sprintf(`
|
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)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||||
RETURNING id`, data.fieldName)
|
RETURNING id`, data.fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pack) InsertObjects(tx *sqlx.Tx) error {
|
func (p *Pack) InsertObjects(tx *sqlx.Tx) error {
|
||||||
relId := &InsertId[string]{id: p.ID, fieldName: "pack_id"}
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
syncDB := NewSyncDB()
|
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertWithCtxParallel(syncDB, tx, p.Ownership, relId)
|
InsertWithCtxParallel(group, ctx, tx, p.Ownership,
|
||||||
InsertSliceParallel(syncDB, tx, p.Index, relId)
|
InsertId[string]{id: strconv.FormatUint(uint64(p.ID), 10), fieldName: "pack_id"})
|
||||||
InsertSliceParallel(syncDB, tx, p.Folders, relId)
|
|
||||||
|
|
||||||
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 {
|
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
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -62,9 +72,9 @@ func (p *Pack) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string
|
|||||||
return ErrNoQuery
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -82,13 +92,13 @@ type PackFolder struct {
|
|||||||
Sort int
|
Sort int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PackFolder) Query(data *InsertId[string]) {
|
func (p *PackFolder) Query(data *InsertId[uint]) {
|
||||||
data.query = fmt.Sprintf(`
|
data.query = fmt.Sprintf(`
|
||||||
INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort)
|
INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName)
|
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 == "" {
|
if data.query == "" {
|
||||||
return ErrNoQuery
|
return ErrNoQuery
|
||||||
}
|
}
|
||||||
@@ -103,7 +113,7 @@ func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
|||||||
return nil
|
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 == "" {
|
if data.query == "" {
|
||||||
return ErrNoQuery
|
return ErrNoQuery
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PackageWarning struct {
|
type PackageWarning struct {
|
||||||
ID string
|
ID uint
|
||||||
|
|
||||||
Key string
|
Key string
|
||||||
Value *PackageWarningsData
|
Value *PackageWarningsData
|
||||||
@@ -16,8 +19,9 @@ type PackageWarning struct {
|
|||||||
|
|
||||||
func (p *PackageWarning) Query(data *InsertId[uint]) {
|
func (p *PackageWarning) Query(data *InsertId[uint]) {
|
||||||
data.query = fmt.Sprintf(`
|
data.query = fmt.Sprintf(`
|
||||||
INSERT INTO package_warnings (%s, id)
|
INSERT INTO package_warnings (%s, key_)
|
||||||
VALUES ($1, $2)`, data.fieldName)
|
VALUES ($1, $2)
|
||||||
|
RETURNING id`, data.fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PackageWarning) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
|
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
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertWithCtx(tx, p.Value, &InsertId[string]{id: p.ID})
|
InsertWithCtx(tx, p.Value, InsertId[uint]{id: p.ID})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -42,16 +46,14 @@ func (p *PackageWarning) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *Inser
|
|||||||
return ErrNoQuery
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertWithCtx(tx, p.Value, &InsertId[string]{id: p.ID})
|
return InsertWithCtx(tx, p.Value, InsertId[uint]{id: p.ID})
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PackageWarningsData struct {
|
type PackageWarningsData struct {
|
||||||
@@ -65,23 +67,27 @@ type PackageWarningsData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PackageWarningsData) InsertObjects(tx *sqlx.Tx) error {
|
func (p *PackageWarningsData) InsertObjects(tx *sqlx.Tx) error {
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
warningData := &InsertId[string]{id: p.ID, fieldName: "package_warnings_data_id", tableName: "package_warnings_data_warning"}
|
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"}
|
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]) {
|
func (p *PackageWarningsData) Query(data *InsertId[uint]) {
|
||||||
data.query = fmt.Sprintf(`
|
data.query = `
|
||||||
INSERT INTO package_warnings_data (%s, id, type, reinstallable, manifest)
|
INSERT INTO package_warnings_data (package_warnings_id, id, type, reinstallable, manifest)
|
||||||
VALUES ($1, $2, $3, $4, $5)`, data.fieldName)
|
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 == "" {
|
if data.query == "" {
|
||||||
return ErrNoQuery
|
return ErrNoQuery
|
||||||
}
|
}
|
||||||
@@ -96,7 +102,7 @@ func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[string]) error
|
|||||||
return p.InsertObjects(tx)
|
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 == "" {
|
if data.query == "" {
|
||||||
return ErrNoQuery
|
return ErrNoQuery
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Playlist struct {
|
type Playlist struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -15,7 +25,58 @@ type Playlist struct {
|
|||||||
Playing bool
|
Playing bool
|
||||||
Stats Stats
|
Stats Stats
|
||||||
Ownership []OwnershipString
|
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 {
|
type Sound struct {
|
||||||
@@ -32,3 +93,39 @@ type Sound struct {
|
|||||||
Volume float64
|
Volume float64
|
||||||
PausedTime 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Relationships struct {
|
type Relationships struct {
|
||||||
@@ -35,15 +39,18 @@ func (r Relationships) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertSliceParallel(syncDB, tx, r.Systems, &InsertId[uint]{id: r.ID, tableName: "relationships_systems"})
|
InsertSliceParallel(group, 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(group, 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(group, 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.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 {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertSliceParallel(syncDB, tx, r.Systems, &InsertId[uint]{id: r.ID, tableName: "relationships_systems"})
|
InsertSliceParallel(group, 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(group, 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(group, 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.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 {
|
type RelationshipsData struct {
|
||||||
ID string
|
ID uint
|
||||||
|
|
||||||
|
Key string
|
||||||
Type string
|
Type string
|
||||||
Manifest string
|
Manifest string
|
||||||
Compatibility Compatibility
|
Compatibility Compatibility
|
||||||
@@ -79,8 +90,8 @@ type RelationshipsData struct {
|
|||||||
|
|
||||||
func (r RelationshipsData) Query(data *InsertId[uint]) {
|
func (r RelationshipsData) Query(data *InsertId[uint]) {
|
||||||
data.query = fmt.Sprintf(`
|
data.query = fmt.Sprintf(`
|
||||||
INSERT INTO %s (relationships_id, id, type, manifest)
|
INSERT INTO %s (relationships_id, key_, type, manifest)
|
||||||
VALUES ($1, $2, $3, $4, $5)`, data.tableName)
|
VALUES ($1, $2, $3, $4)`, data.tableName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r RelationshipsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
|
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
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
InsertWithCtxParallel(group, ctx, tx, r.Compatibility, InsertId[string]{id: strconv.FormatUint(uint64(r.ID), 10), fieldName: fmt.Sprintf("%s_id", data.tableName)})
|
||||||
InsertWithCtxParallel(syncDB, tx, r.Compatibility, &InsertId[string]{id: r.ID, 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 {
|
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
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDB := NewSyncDB()
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
InsertWithCtxParallel(group, ctx, tx, r.Compatibility, InsertId[string]{id: strconv.FormatUint(uint64(r.ID), 10), fieldName: fmt.Sprintf("%s_id", data.tableName)})
|
||||||
InsertWithCtxParallel(syncDB, tx, r.Compatibility, &InsertId[string]{id: r.ID, fieldName: fmt.Sprintf("%s_id", data.tableName)})
|
|
||||||
|
|
||||||
return nil
|
return group.Wait()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type Release struct {
|
|||||||
|
|
||||||
func (r *Release) Query(data *InsertId[uint]) {
|
func (r *Release) Query(data *InsertId[uint]) {
|
||||||
data.query = fmt.Sprintf(`
|
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)
|
time, channel, suffix)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||||
RETURNING id`, data.fieldName)
|
RETURNING id`, data.fieldName)
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Setting struct {
|
type Setting struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -7,3 +17,52 @@ type Setting struct {
|
|||||||
Value string
|
Value string
|
||||||
Stats Stats
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Setup struct {
|
type Setup struct {
|
||||||
@@ -28,29 +31,32 @@ type Setup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Setup) InsertObjects(tx *sqlx.Tx) error {
|
func (s *Setup) InsertObjects(tx *sqlx.Tx) error {
|
||||||
relData := &InsertId[uint]{id: s.ID, fieldName: "setup_id"}
|
relData := InsertId[uint]{id: s.ID, fieldName: "setup_id"}
|
||||||
syncDB := NewSyncDB()
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertWithCtxParallel(syncDB, tx, &s.CoreUpdate, relData)
|
InsertWithCtxParallel(group, ctx, tx, &s.CoreUpdate, relData)
|
||||||
InsertWithCtxParallel(syncDB, tx, &s.FeaturedContent, relData)
|
InsertWithCtxParallel(group, ctx, tx, &s.FeaturedContent, relData)
|
||||||
InsertWithCtxParallel(syncDB, tx, &s.Files, relData)
|
InsertWithCtxParallel(group, ctx, tx, &s.Files, relData)
|
||||||
InsertWithCtxParallel(syncDB, tx, s.Options, relData)
|
InsertWithCtxParallel(group, ctx, tx, s.Options, relData)
|
||||||
InsertWithCtxParallel(syncDB, tx, &s.Release, relData)
|
InsertWithCtxParallel(group, ctx, tx, &s.Release, relData)
|
||||||
|
|
||||||
InsertSliceParallel(syncDB, tx, s.Languages, relData)
|
InsertSliceParallel(group, tx, s.Languages, relData)
|
||||||
InsertSliceParallel(syncDB, tx, s.Modules, relData)
|
InsertSliceParallel(group, tx, s.Modules, relData)
|
||||||
InsertSliceParallel(syncDB, tx, s.News, relData)
|
InsertSliceParallel(group, tx, s.News, relData)
|
||||||
InsertSliceParallel(syncDB, tx, s.PackageWarnings, relData)
|
InsertSliceParallel(group, tx, s.PackageWarnings, relData)
|
||||||
|
|
||||||
relDataString := &InsertId[string]{
|
relDataString := InsertId[string]{
|
||||||
id: strconv.FormatUint(uint64(s.ID), 10),
|
id: strconv.FormatUint(uint64(s.ID), 10),
|
||||||
fieldName: "setup_id",
|
fieldName: "setup_id",
|
||||||
}
|
}
|
||||||
InsertSliceParallel(syncDB, tx, s.Systems, relDataString)
|
InsertSliceParallel(group, tx, s.Systems, relDataString)
|
||||||
InsertSliceParallel(syncDB, tx, s.Worlds, 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 {
|
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)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
@@ -9,3 +16,39 @@ type Stats struct {
|
|||||||
LastModifiedBy string
|
LastModifiedBy string
|
||||||
ModifiedTime int64
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func (s *Style) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
|||||||
|
|
||||||
args := []any{data.id, s.Src}
|
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 {
|
if err != nil {
|
||||||
return err
|
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}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type System struct {
|
type System struct {
|
||||||
@@ -54,30 +57,33 @@ func (s *System) Query(data *InsertId[string]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *System) InsertObjects(tx *sqlx.Tx) error {
|
func (s *System) InsertObjects(tx *sqlx.Tx) error {
|
||||||
relId := &InsertId[string]{id: s.ID, fieldName: "system_id"}
|
relId := InsertId[string]{id: s.ID, fieldName: "system_id"}
|
||||||
syncDB := NewSyncDB()
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertWithCtxParallel(syncDB, tx, s.Compatibility, relId)
|
InsertWithCtxParallel(group, ctx, tx, s.Compatibility, relId)
|
||||||
InsertWithCtxParallel(syncDB, tx, s.Relationships, relId)
|
InsertWithCtxParallel(group, ctx, tx, s.Relationships, relId)
|
||||||
InsertWithCtxParallel(syncDB, tx, s.DocumentTypes, relId)
|
InsertWithCtxParallel(group, ctx, tx, s.DocumentTypes, relId)
|
||||||
InsertWithCtxParallel(syncDB, tx, s.Grid, relId)
|
InsertWithCtxParallel(group, ctx, tx, s.Grid, relId)
|
||||||
|
|
||||||
esModulesRelId := &InsertId[string]{id: s.ID, fieldName: "system_id", tableName: "es_modules"}
|
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"}
|
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"}
|
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(group, tx, s.Authors, relId)
|
||||||
InsertSliceParallel(syncDB, tx, s.Media, relId)
|
InsertSliceParallel(group, tx, s.Media, relId)
|
||||||
InsertSliceParallel(syncDB, tx, s.Styles, relId)
|
InsertSliceParallel(group, tx, s.Styles, relId)
|
||||||
InsertSliceParallel(syncDB, tx, s.Languages, relId)
|
InsertSliceParallel(group, tx, s.Languages, relId)
|
||||||
InsertSliceParallel(syncDB, tx, s.Packs, relId)
|
InsertSliceParallel(group, tx, s.Packs, relId)
|
||||||
InsertSliceParallel(syncDB, tx, s.PackFolders, 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 {
|
func (s *System) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -13,7 +23,58 @@ type Table struct {
|
|||||||
DisplayRoll bool
|
DisplayRoll bool
|
||||||
Stats Stats
|
Stats Stats
|
||||||
Ownership []OwnershipString
|
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 {
|
type TableResult struct {
|
||||||
@@ -28,3 +89,52 @@ type TableResult struct {
|
|||||||
Stats Stats
|
Stats Stats
|
||||||
Range []int
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,3 +62,40 @@ type SystemUpdate struct {
|
|||||||
HasUpdate bool
|
HasUpdate bool
|
||||||
Version string
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
@@ -13,9 +22,95 @@ type User struct {
|
|||||||
Hotbar []UserHotbar
|
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 {
|
type UserHotbar struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
|
||||||
Key int
|
Key int
|
||||||
Value string
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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 {
|
type AllowedIds interface {
|
||||||
@@ -25,75 +26,40 @@ type InsertId[T AllowedIds] struct {
|
|||||||
query string
|
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 {
|
type Insertable[T AllowedIds] interface {
|
||||||
Query(data *InsertId[T])
|
Query(data *InsertId[T])
|
||||||
Insert(tx *sqlx.Tx, relId *InsertId[T]) error
|
Insert(tx *sqlx.Tx, relId *InsertId[T]) error
|
||||||
InsertCtx(ctx context.Context, 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)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
data.Query(relId)
|
data.Query(&relId)
|
||||||
return data.InsertCtx(ctx, tx, relId)
|
return data.InsertCtx(ctx, tx, &relId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InsertWithCtxParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDB, tx *sqlx.Tx, data I, relId *InsertId[T]) {
|
func InsertWithCtxParallel[T AllowedIds, I Insertable[T]](g *errgroup.Group, ctx context.Context, tx *sqlx.Tx, data I, relId InsertId[T]) {
|
||||||
syncDb.wg.Go(func() {
|
g.Go(func() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
data.Query(relId)
|
data.Query(&relId)
|
||||||
err := data.InsertCtx(ctx, tx, relId)
|
err := data.InsertCtx(ctx, tx, &relId)
|
||||||
if err != nil {
|
return err
|
||||||
syncDb.errChan <- 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)
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
data[0].Query(relId)
|
data[0].Query(&relId)
|
||||||
}
|
}
|
||||||
for i := range data {
|
for i := range data {
|
||||||
err := data[i].InsertCtx(ctx, tx, relId)
|
err := data[i].InsertCtx(ctx, tx, &relId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -101,32 +67,25 @@ func InsertSlice[T AllowedIds, I Insertable[T]](tx *sqlx.Tx, data []I, relId *In
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func InsertSliceParallel[T AllowedIds, I Insertable[T]](syncDb *SyncDB, tx *sqlx.Tx, data []I, relId *InsertId[T]) {
|
func InsertSliceParallel[T AllowedIds, I Insertable[T]](g *errgroup.Group, tx *sqlx.Tx, data []I, relId InsertId[T]) {
|
||||||
syncDb.wg.Go(func() {
|
g.Go(func() error {
|
||||||
wg := sync.WaitGroup{}
|
wg, _ := errgroup.WithContext(context.Background())
|
||||||
errChan := make(chan error)
|
|
||||||
defer close(errChan)
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
data[0].Query(relId)
|
data[0].Query(&relId)
|
||||||
}
|
}
|
||||||
for i := range data {
|
for i := range data {
|
||||||
wg.Go(func() {
|
wg.Go(func() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
err = data[i].InsertCtx(ctx, tx, relId)
|
err = data[i].InsertCtx(ctx, tx, &relId)
|
||||||
if err != nil {
|
return err
|
||||||
errChan <- err
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = WaitSync(&wg, errChan)
|
return wg.Wait()
|
||||||
if err != nil {
|
|
||||||
syncDb.errChan <- err
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,30 +106,69 @@ func InsertSimpleSlice[T AllowedIds, I any](tx *sqlx.Tx, data []I, relId *Insert
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func InsertSimpleSliceParallel[T AllowedIds, I any](syncDb *SyncDB, tx *sqlx.Tx, data []I, relId *InsertId[T]) {
|
func InsertSimpleSliceParallel[T AllowedIds, I any](g *errgroup.Group, tx *sqlx.Tx, data []I, relId *InsertId[T]) {
|
||||||
syncDb.wg.Go(func() {
|
g.Go(func() error {
|
||||||
wg := sync.WaitGroup{}
|
wg, _ := errgroup.WithContext(context.Background())
|
||||||
errChan := make(chan error)
|
|
||||||
defer close(errChan)
|
|
||||||
|
|
||||||
query := fmt.Sprintf(`
|
query := fmt.Sprintf(`
|
||||||
INSERT INTO %s (%s, value)
|
INSERT INTO %s (%s, value)
|
||||||
VALUES ($1, $2)`, relId.tableName, relId.fieldName)
|
VALUES ($1, $2)`, relId.tableName, relId.fieldName)
|
||||||
for i := range data {
|
for i := range data {
|
||||||
wg.Go(func() {
|
wg.Go(func() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, err := tx.ExecContext(ctx, query, relId.id, data[i])
|
_, err := tx.ExecContext(ctx, query, relId.id, data[i])
|
||||||
if err != nil {
|
return err
|
||||||
errChan <- err
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
err := WaitSync(&wg, errChan)
|
return wg.Wait()
|
||||||
if err != nil {
|
|
||||||
syncDb.errChan <- err
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type World struct {
|
type World struct {
|
||||||
@@ -53,28 +56,31 @@ func (w *World) Query(data *InsertId[string]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) InsertObjects(tx *sqlx.Tx) error {
|
func (w *World) InsertObjects(tx *sqlx.Tx) error {
|
||||||
relId := &InsertId[string]{id: w.ID, fieldName: "world_id"}
|
relId := InsertId[string]{id: w.ID, fieldName: "world_id"}
|
||||||
syncDB := NewSyncDB()
|
group, ctx := errgroup.WithContext(context.Background())
|
||||||
defer close(syncDB.errChan)
|
|
||||||
|
|
||||||
InsertWithCtxParallel(syncDB, tx, w.Compatibility, relId)
|
InsertWithCtxParallel(group, ctx, tx, w.Compatibility, relId)
|
||||||
InsertWithCtxParallel(syncDB, tx, w.Relationships, relId)
|
InsertWithCtxParallel(group, ctx, tx, w.Relationships, relId)
|
||||||
|
|
||||||
esModulesRelId := &InsertId[string]{id: w.ID, fieldName: "world_id", tableName: "es_modules"}
|
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"}
|
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"}
|
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(group, tx, w.Authors, relId)
|
||||||
InsertSliceParallel(syncDB, tx, w.Media, relId)
|
InsertSliceParallel(group, tx, w.Media, relId)
|
||||||
InsertSliceParallel(syncDB, tx, w.Styles, relId)
|
InsertSliceParallel(group, tx, w.Styles, relId)
|
||||||
InsertSliceParallel(syncDB, tx, w.Languages, relId)
|
InsertSliceParallel(group, tx, w.Languages, relId)
|
||||||
InsertSliceParallel(syncDB, tx, w.Packs, relId)
|
InsertSliceParallel(group, tx, w.Packs, relId)
|
||||||
InsertSliceParallel(syncDB, tx, w.PackFolders, 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 {
|
func (w *World) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
|
||||||
|
|||||||
@@ -21,27 +21,31 @@ type CardDeck struct {
|
|||||||
// Cards0System any `json:"system"`
|
// Cards0System any `json:"system"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CardDeck) ToDB(dest *db.CardDeck) bool {
|
func (c *CardDeck) ToDB(dest **db.CardDeck) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = c.Name
|
cardDeck := &db.CardDeck{
|
||||||
dest.Type = c.Type
|
Name: c.Name,
|
||||||
dest.Description = c.Description
|
Type: c.Type,
|
||||||
dest.Img = c.Img
|
Description: c.Description,
|
||||||
dest.Width = c.Width
|
Img: c.Img,
|
||||||
dest.Height = c.Height
|
Width: c.Width,
|
||||||
dest.Rotation = c.Rotation
|
Height: c.Height,
|
||||||
dest.DisplayCount = c.DisplayCount
|
Rotation: c.Rotation,
|
||||||
dest.Folder = c.Folder
|
DisplayCount: c.DisplayCount,
|
||||||
dest.Sort = c.Sort
|
Folder: c.Folder,
|
||||||
dest.ID = c.ID
|
Sort: c.Sort,
|
||||||
|
ID: c.ID,
|
||||||
|
}
|
||||||
|
|
||||||
c.Stats.ToDB(&dest.Stats)
|
c.Stats.ToDB(&cardDeck.Stats)
|
||||||
c.Ownership.ToDB(&dest.Ownership)
|
c.Ownership.ToDB(&cardDeck.Ownership)
|
||||||
|
|
||||||
CopySliceToDB(&dest.Cards, c.Cards)
|
CopySliceToDB(&cardDeck.Cards, c.Cards)
|
||||||
|
|
||||||
|
*dest = cardDeck
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -67,29 +71,33 @@ type Card struct {
|
|||||||
// System any `json:"system"`
|
// System any `json:"system"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Card) ToDB(dest *db.Card) bool {
|
func (c *Card) ToDB(dest **db.Card) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = c.Name
|
card := &db.Card{
|
||||||
dest.Width = c.Width
|
Name: c.Name,
|
||||||
dest.Height = c.Height
|
Width: c.Width,
|
||||||
dest.Rotation = c.Rotation
|
Height: c.Height,
|
||||||
dest.Type = c.Type
|
Rotation: c.Rotation,
|
||||||
dest.Value = c.Value
|
Type: c.Type,
|
||||||
dest.Suit = c.Suit
|
Value: c.Value,
|
||||||
dest.Description = c.Description
|
Suit: c.Suit,
|
||||||
dest.Face = c.Face
|
Description: c.Description,
|
||||||
dest.Drawn = c.Drawn
|
Face: c.Face,
|
||||||
dest.Origin = c.Origin
|
Drawn: c.Drawn,
|
||||||
dest.ID = c.ID
|
Origin: c.Origin,
|
||||||
dest.Sort = c.Sort
|
ID: c.ID,
|
||||||
|
Sort: c.Sort,
|
||||||
|
}
|
||||||
|
|
||||||
c.Back.ToDB(&dest.Back)
|
c.Back.ToDB(&card.Back)
|
||||||
c.Stats.ToDB(&dest.Stats)
|
c.Stats.ToDB(&card.Stats)
|
||||||
|
|
||||||
CopySliceToDB(&dest.Faces, c.Faces)
|
CopySliceToDB(&card.Faces, c.Faces)
|
||||||
|
|
||||||
|
*dest = card
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,28 @@ type Combat struct {
|
|||||||
// Flags any `json:"flags"`
|
// Flags any `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Combat) ToDB(dest *db.Combat) bool {
|
func (c *Combat) ToDB(dest **db.Combat) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.ID = c.Id
|
combat := &db.Combat{
|
||||||
dest.Type = c.Type
|
ID: c.Id,
|
||||||
dest.Scene = c.Scene
|
Type: c.Type,
|
||||||
dest.Active = c.Active
|
Scene: c.Scene,
|
||||||
dest.Round = c.Round
|
Active: c.Active,
|
||||||
dest.Turn = c.Turn
|
Round: c.Round,
|
||||||
dest.Sort = c.Sort
|
Turn: c.Turn,
|
||||||
|
Sort: c.Sort,
|
||||||
|
}
|
||||||
|
|
||||||
c.Stats.ToDB(&dest.Stats)
|
c.Stats.ToDB(&combat.Stats)
|
||||||
|
|
||||||
copy(dest.Groups, c.Groups)
|
combat.Groups = make([]string, len(c.Groups))
|
||||||
CopySliceToDB(&dest.Combatants, c.Combatants)
|
copy(combat.Groups, c.Groups)
|
||||||
|
CopySliceToDB(&combat.Combatants, c.Combatants)
|
||||||
|
|
||||||
|
*dest = combat
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -54,22 +59,27 @@ type Combatant struct {
|
|||||||
// Flags any `json:"flags"`
|
// Flags any `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Combatant) ToDB(dest *db.Combatant) bool {
|
func (c *Combatant) ToDB(dest **db.Combatant) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.TokenId = c.TokenId
|
combatant := &db.Combatant{
|
||||||
dest.SceneId = c.SceneId
|
TokenId: c.TokenId,
|
||||||
dest.ActorId = c.ActorId
|
SceneId: c.SceneId,
|
||||||
dest.Hidden = c.Hidden
|
ActorId: c.ActorId,
|
||||||
dest.ID = c.Id
|
Hidden: c.Hidden,
|
||||||
dest.Type = c.Type
|
ID: c.Id,
|
||||||
dest.Img = c.Img
|
Type: c.Type,
|
||||||
dest.Initiative = c.Initiative
|
Img: c.Img,
|
||||||
dest.Defeated = c.Defeated
|
Initiative: c.Initiative,
|
||||||
dest.Group = c.Group
|
Defeated: c.Defeated,
|
||||||
c.Stats.ToDB(&dest.Stats)
|
Group: c.Group,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Stats.ToDB(&combatant.Stats)
|
||||||
|
|
||||||
|
*dest = combatant
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ func (d *DocumentTypes) ToDB(dest *db.DocumentTypes) bool {
|
|||||||
|
|
||||||
dest.Data = make([]*db.DocumentTypeData, 2)
|
dest.Data = make([]*db.DocumentTypeData, 2)
|
||||||
|
|
||||||
|
dest.Data[0] = &db.DocumentTypeData{Type: "Actor"}
|
||||||
d.Actor.ToDB(dest.Data[0])
|
d.Actor.ToDB(dest.Data[0])
|
||||||
dest.Data[0].Type = "Actor"
|
|
||||||
|
|
||||||
|
dest.Data[1] = &db.DocumentTypeData{Type: "Item"}
|
||||||
d.Item.ToDB(dest.Data[1])
|
d.Item.ToDB(dest.Data[1])
|
||||||
dest.Data[1].Type = "Item"
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ func (f *Folder) ToDB(dest **db.Folder) bool {
|
|||||||
Sorting: f.Sorting,
|
Sorting: f.Sorting,
|
||||||
Color: f.Color,
|
Color: f.Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
folder.Packs = make([]string, len(f.Packs))
|
||||||
copy(folder.Packs, f.Packs)
|
copy(folder.Packs, f.Packs)
|
||||||
CopySliceToDB(&folder.Folders, f.Folders)
|
CopySliceToDB(&folder.Folders, f.Folders)
|
||||||
|
|
||||||
@@ -41,20 +43,25 @@ type WorldFolder struct {
|
|||||||
// Flags any `json:"flags,omitempty"`
|
// Flags any `json:"flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldFolder) ToDB(dest *db.WorldFolder) bool {
|
func (w *WorldFolder) ToDB(dest **db.WorldFolder) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = w.Name
|
worldFolder := &db.WorldFolder{
|
||||||
dest.Type = w.Type
|
Name: w.Name,
|
||||||
dest.ID = w.ID
|
Type: w.Type,
|
||||||
dest.Folder = w.Folder
|
ID: w.ID,
|
||||||
dest.Sorting = w.Sorting
|
Folder: w.Folder,
|
||||||
dest.Sort = w.Sort
|
Sorting: w.Sorting,
|
||||||
w.Stats.ToDB(&dest.Stats)
|
Sort: w.Sort,
|
||||||
dest.Description = w.Description
|
Description: w.Description,
|
||||||
dest.Color = w.Color
|
Color: w.Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Stats.ToDB(&worldFolder.Stats)
|
||||||
|
|
||||||
|
*dest = worldFolder
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,23 +55,25 @@ func (g *Game) ToDB(dest *db.Game) bool {
|
|||||||
g.Options.ToDB(&dest.Options)
|
g.Options.ToDB(&dest.Options)
|
||||||
g.CoreUpdate.ToDB(&dest.CoreUpdate)
|
g.CoreUpdate.ToDB(&dest.CoreUpdate)
|
||||||
g.SystemUpdate.ToDB(&dest.SystemUpdate)
|
g.SystemUpdate.ToDB(&dest.SystemUpdate)
|
||||||
|
|
||||||
|
dest.ActiveUsers = make([]string, len(g.ActiveUsers))
|
||||||
copy(dest.ActiveUsers, g.ActiveUsers)
|
copy(dest.ActiveUsers, g.ActiveUsers)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &dest.Modules, g.Modules)
|
CopySliceToDBParallel(&wg, &dest.Modules, g.Modules)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Packs, g.Packs)
|
CopySliceToDBParallel(&wg, &dest.Packs, g.Packs)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Messages, g.Messages)
|
CopySliceToDBParallel(&wg, &dest.Messages, g.Messages)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Combats, g.Combats)
|
CopySliceToDBParallel(&wg, &dest.Combats, g.Combats)
|
||||||
go CopySliceToDBParallel(&wg, &dest.CardDeck, g.CardDeck)
|
CopySliceToDBParallel(&wg, &dest.CardDeck, g.CardDeck)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Users, g.Users)
|
CopySliceToDBParallel(&wg, &dest.Users, g.Users)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Macros, g.Macros)
|
CopySliceToDBParallel(&wg, &dest.Macros, g.Macros)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Folders, g.Folders)
|
CopySliceToDBParallel(&wg, &dest.Folders, g.Folders)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Items, g.Items)
|
CopySliceToDBParallel(&wg, &dest.Items, g.Items)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Settings, g.Settings)
|
CopySliceToDBParallel(&wg, &dest.Settings, g.Settings)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Journals, g.Journals)
|
CopySliceToDBParallel(&wg, &dest.Journals, g.Journals)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Tables, g.Tables)
|
CopySliceToDBParallel(&wg, &dest.Tables, g.Tables)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Playlists, g.Playlists)
|
CopySliceToDBParallel(&wg, &dest.Playlists, g.Playlists)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Actors, g.Actors)
|
CopySliceToDBParallel(&wg, &dest.Actors, g.Actors)
|
||||||
// go CopySliceToDBParallel(&wg, &dest.Scenes, g.Scenes)
|
// go CopySliceToDBParallel(&wg, &dest.Scenes, g.Scenes)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
|||||||
@@ -16,19 +16,23 @@ type Item struct {
|
|||||||
// Effects []any `json:"effects"`
|
// Effects []any `json:"effects"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Item) ToDB(dest *db.Item) bool {
|
func (i *Item) ToDB(dest **db.Item) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Img = i.Img
|
item := &db.Item{
|
||||||
dest.Name = i.Name
|
Img: i.Img,
|
||||||
dest.Type = i.Type
|
Name: i.Name,
|
||||||
dest.Folder = i.Folder
|
Type: i.Type,
|
||||||
dest.ID = i.ID
|
Folder: i.Folder,
|
||||||
dest.Sort = i.Sort
|
ID: i.ID,
|
||||||
|
Sort: i.Sort,
|
||||||
|
}
|
||||||
|
|
||||||
i.Stats.ToDB(&dest.Stats)
|
i.Stats.ToDB(&item.Stats)
|
||||||
|
|
||||||
|
*dest = item
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,21 @@ type Journal struct {
|
|||||||
// Categories []any `json:"categories"`
|
// Categories []any `json:"categories"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Journal) ToDB(dest *db.Journal) bool {
|
func (j *Journal) ToDB(dest **db.Journal) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = j.Name
|
journal := &db.Journal{
|
||||||
dest.Sort = j.Sort
|
Name: j.Name,
|
||||||
dest.ID = j.ID
|
Sort: j.Sort,
|
||||||
|
ID: j.ID,
|
||||||
|
}
|
||||||
|
|
||||||
OwnershipToDB(&dest.Ownership, j.Ownership)
|
OwnershipToDB(&journal.Ownership, j.Ownership)
|
||||||
CopySliceToDB(&dest.Pages, j.Pages)
|
CopySliceToDB(&journal.Pages, j.Pages)
|
||||||
|
|
||||||
|
*dest = journal
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,23 +19,25 @@ type JournalPage struct {
|
|||||||
// Category any `json:"category"`
|
// Category any `json:"category"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JournalPage) ToDB(dest *db.JournalPage) bool {
|
func (j *JournalPage) ToDB(dest **db.JournalPage) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = j.Name
|
journalPage := &db.JournalPage{
|
||||||
dest.Type = j.Type
|
Name: j.Name,
|
||||||
dest.ID = j.ID
|
Type: j.Type,
|
||||||
dest.Src = j.Src
|
ID: j.ID,
|
||||||
dest.Sort = j.Sort
|
Src: j.Src,
|
||||||
|
Sort: j.Sort,
|
||||||
|
}
|
||||||
|
|
||||||
j.Text.ToDB(&dest.Text)
|
j.Text.ToDB(&journalPage.Text)
|
||||||
j.Title.ToDB(&dest.Title)
|
j.Title.ToDB(&journalPage.Title)
|
||||||
j.Video.ToDB(&dest.Video)
|
j.Video.ToDB(&journalPage.Video)
|
||||||
j.Stats.ToDB(&dest.Stats)
|
j.Stats.ToDB(&journalPage.Stats)
|
||||||
|
|
||||||
OwnershipToDB(&dest.Ownership, j.Ownership)
|
OwnershipToDB(&journalPage.Ownership, j.Ownership)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,28 @@ type Macro struct {
|
|||||||
// Flags any `json:"flags,omitempty"`
|
// Flags any `json:"flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Macro) ToDB(dest *db.Macro) bool {
|
func (m *Macro) ToDB(dest **db.Macro) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Command = m.Command
|
macro := &db.Macro{
|
||||||
dest.Name = m.Name
|
Command: m.Command,
|
||||||
dest.Type = m.Type
|
Name: m.Name,
|
||||||
dest.Img = m.Img
|
Type: m.Type,
|
||||||
dest.ID = m.ID
|
Img: m.Img,
|
||||||
dest.Author = m.Author
|
ID: m.ID,
|
||||||
dest.Scope = m.Scope
|
Author: m.Author,
|
||||||
dest.Folder = m.Folder
|
Scope: m.Scope,
|
||||||
dest.Sort = m.Sort
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,27 +21,33 @@ type Message struct {
|
|||||||
// Flags any `json:"flags"`
|
// Flags any `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) ToDB(dest *db.Message) bool {
|
func (m *Message) ToDB(dest **db.Message) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Content = m.Content
|
message := &db.Message{
|
||||||
dest.Style = m.Style
|
Content: m.Content,
|
||||||
dest.Author = m.Author
|
Style: m.Style,
|
||||||
dest.ID = m.Id
|
Author: m.Author,
|
||||||
dest.Type = m.Type
|
ID: m.Id,
|
||||||
dest.Timestamp = m.Timestamp
|
Type: m.Type,
|
||||||
dest.Flavor = m.Flavor
|
Timestamp: m.Timestamp,
|
||||||
dest.Blind = m.Blind
|
Flavor: m.Flavor,
|
||||||
dest.Sound = m.Sound
|
Blind: m.Blind,
|
||||||
dest.Emote = m.Emote
|
Sound: m.Sound,
|
||||||
|
Emote: m.Emote,
|
||||||
|
}
|
||||||
|
|
||||||
m.Speaker.ToDB(&dest.Speaker)
|
m.Speaker.ToDB(&message.Speaker)
|
||||||
m.Stats.ToDB(&dest.Stats)
|
m.Stats.ToDB(&message.Stats)
|
||||||
|
|
||||||
copy(dest.Whisper, m.Whisper)
|
message.Whisper = make([]string, len(m.Whisper))
|
||||||
copy(dest.Rolls, m.Rolls)
|
copy(message.Whisper, m.Whisper)
|
||||||
|
message.Rolls = make([]string, len(m.Rolls))
|
||||||
|
copy(message.Rolls, m.Rolls)
|
||||||
|
|
||||||
|
*dest = message
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,8 +74,11 @@ func (m *Module) ToDB(dest **db.Module) bool {
|
|||||||
Active: m.Active,
|
Active: m.Active,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.Scripts = make([]string, len(m.Scripts))
|
||||||
copy(module.Scripts, m.Scripts)
|
copy(module.Scripts, m.Scripts)
|
||||||
|
module.Esmodules = make([]string, len(m.Esmodules))
|
||||||
copy(module.Esmodules, m.Esmodules)
|
copy(module.Esmodules, m.Esmodules)
|
||||||
|
module.Tags = make([]string, len(m.Tags))
|
||||||
copy(module.Tags, m.Tags)
|
copy(module.Tags, m.Tags)
|
||||||
|
|
||||||
m.Compatibility.ToDB(&module.Compatibility)
|
m.Compatibility.ToDB(&module.Compatibility)
|
||||||
@@ -83,12 +86,12 @@ func (m *Module) ToDB(dest **db.Module) bool {
|
|||||||
m.DocumentTypes.ToDB(&module.DocumentTypes)
|
m.DocumentTypes.ToDB(&module.DocumentTypes)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &module.Authors, m.Authors)
|
CopySliceToDBParallel(&wg, &module.Authors, m.Authors)
|
||||||
go CopySliceToDBParallel(&wg, &module.Media, m.Media)
|
CopySliceToDBParallel(&wg, &module.Media, m.Media)
|
||||||
go CopySliceToDBParallel(&wg, &module.Styles, m.Styles)
|
CopySliceToDBParallel(&wg, &module.Styles, m.Styles)
|
||||||
go CopySliceToDBParallel(&wg, &module.Languages, m.Languages)
|
CopySliceToDBParallel(&wg, &module.Languages, m.Languages)
|
||||||
go CopySliceToDBParallel(&wg, &module.Packs, m.Packs)
|
CopySliceToDBParallel(&wg, &module.Packs, m.Packs)
|
||||||
go CopySliceToDBParallel(&wg, &module.PackFolders, m.PackFolders)
|
CopySliceToDBParallel(&wg, &module.PackFolders, m.PackFolders)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
*dest = module
|
*dest = module
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ func (p *Pack) ToDB(dest **db.Pack) bool {
|
|||||||
System: p.System,
|
System: p.System,
|
||||||
PackageType: p.PackageType,
|
PackageType: p.PackageType,
|
||||||
PackageName: p.PackageName,
|
PackageName: p.PackageName,
|
||||||
ID: p.Id,
|
Key: p.Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Ownership.ToDB(&pack.Ownership)
|
p.Ownership.ToDB(&pack.Ownership)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &pack.Index, p.Index)
|
CopySliceToDBParallel(&wg, &pack.Index, p.Index)
|
||||||
go CopySliceToDBParallel(&wg, &pack.Folders, p.Folders)
|
CopySliceToDBParallel(&wg, &pack.Folders, p.Folders)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
*dest = pack
|
*dest = pack
|
||||||
|
|||||||
@@ -11,18 +11,25 @@ type PackageWarningsData struct {
|
|||||||
Manifest string `json:"manifest,omitempty"`
|
Manifest string `json:"manifest,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PackageWarningsData) ToDB(dest *db.PackageWarningsData) bool {
|
func (p *PackageWarningsData) ToDB(dest **db.PackageWarningsData) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.ID = p.Id
|
packageData := &db.PackageWarningsData{
|
||||||
dest.Type = p.Type
|
ID: p.Id,
|
||||||
dest.Reinstallable = p.Reinstallable
|
Type: p.Type,
|
||||||
dest.Manifest = p.Manifest
|
Reinstallable: p.Reinstallable,
|
||||||
|
Manifest: p.Manifest,
|
||||||
|
}
|
||||||
|
|
||||||
copy(dest.Warning, p.Warning)
|
packageData.Warning = make([]string, len(p.Warning))
|
||||||
copy(dest.Error, p.Error)
|
copy(packageData.Warning, p.Warning)
|
||||||
|
|
||||||
|
packageData.Error = make([]string, len(p.Error))
|
||||||
|
copy(packageData.Error, p.Error)
|
||||||
|
|
||||||
|
*dest = packageData
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,28 +20,30 @@ type Playlist struct {
|
|||||||
// Flags any `json:"flags,omitempty"`
|
// Flags any `json:"flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Playlist) ToDB(dest *db.Playlist) bool {
|
func (p *Playlist) ToDB(dest **db.Playlist) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = p.Name
|
playlist := &db.Playlist{
|
||||||
dest.ID = p.ID
|
Name: p.Name,
|
||||||
dest.Mode = p.Mode
|
ID: p.ID,
|
||||||
dest.Playing = p.Playing
|
Mode: p.Mode,
|
||||||
dest.Fade = p.Fade
|
Playing: p.Playing,
|
||||||
dest.Folder = p.Folder
|
Fade: p.Fade,
|
||||||
dest.Sorting = p.Sorting
|
Folder: p.Folder,
|
||||||
dest.Seed = p.Seed
|
Sorting: p.Sorting,
|
||||||
dest.Sort = p.Sort
|
Seed: p.Seed,
|
||||||
dest.Description = p.Description
|
Sort: p.Sort,
|
||||||
dest.Channel = p.Channel
|
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
|
return true
|
||||||
}
|
}
|
||||||
@@ -61,22 +63,26 @@ type Sound struct {
|
|||||||
// Flags any `json:"flags"`
|
// Flags any `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sound) ToDB(dest *db.Sound) bool {
|
func (s *Sound) ToDB(dest **db.Sound) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = s.Name
|
sound := &db.Sound{
|
||||||
dest.Path = s.Path
|
Name: s.Name,
|
||||||
dest.ID = s.ID
|
Path: s.Path,
|
||||||
dest.Playing = s.Playing
|
ID: s.ID,
|
||||||
dest.PausedTime = s.PausedTime
|
Playing: s.Playing,
|
||||||
dest.Repeat = s.Repeat
|
PausedTime: s.PausedTime,
|
||||||
dest.Volume = s.Volume
|
Repeat: s.Repeat,
|
||||||
dest.Fade = s.Fade
|
Volume: s.Volume,
|
||||||
dest.Sort = s.Sort
|
Fade: s.Fade,
|
||||||
dest.Channel = s.Channel
|
Sort: s.Sort,
|
||||||
dest.Description = s.Description
|
Channel: s.Channel,
|
||||||
|
Description: s.Description,
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = sound
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ func (r *Relationships) ToDB(dest *db.Relationships) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &dest.Systems, r.Systems)
|
CopySliceToDBParallel(&wg, &dest.Systems, r.Systems)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Requires, r.Requires)
|
CopySliceToDBParallel(&wg, &dest.Requires, r.Requires)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Recommends, r.Recommends)
|
CopySliceToDBParallel(&wg, &dest.Recommends, r.Recommends)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Conflicts, r.Conflicts)
|
CopySliceToDBParallel(&wg, &dest.Conflicts, r.Conflicts)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -41,7 +41,7 @@ func (r *RelationshipsData) ToDB(dest *db.RelationshipsData) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.ID = r.Id
|
dest.Key = r.Id
|
||||||
dest.Type = r.Type
|
dest.Type = r.Type
|
||||||
dest.Manifest = r.Manifest
|
dest.Manifest = r.Manifest
|
||||||
|
|
||||||
|
|||||||
@@ -85,12 +85,12 @@ func (s *Scene) ToDB(dest *db.Scene) bool {
|
|||||||
OwnershipToDB(&dest.Ownership, s.Ownership)
|
OwnershipToDB(&dest.Ownership, s.Ownership)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &dest.Drawings, s.Drawings)
|
CopySliceToDBParallel(&wg, &dest.Drawings, s.Drawings)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Tokens, s.Tokens)
|
CopySliceToDBParallel(&wg, &dest.Tokens, s.Tokens)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Lights, s.Lights)
|
CopySliceToDBParallel(&wg, &dest.Lights, s.Lights)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Notes, s.Notes)
|
CopySliceToDBParallel(&wg, &dest.Notes, s.Notes)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Sounds, s.Sounds)
|
CopySliceToDBParallel(&wg, &dest.Sounds, s.Sounds)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Walls, s.Walls)
|
CopySliceToDBParallel(&wg, &dest.Walls, s.Walls)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -10,15 +10,20 @@ type Setting struct {
|
|||||||
Stats Stats `json:"_stats"`
|
Stats Stats `json:"_stats"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Setting) ToDB(dest *db.Setting) bool {
|
func (s *Setting) ToDB(dest **db.Setting) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Key = s.Key
|
setting := &db.Setting{
|
||||||
dest.Value = s.Value
|
Key: s.Key,
|
||||||
dest.ID = s.ID
|
Value: s.Value,
|
||||||
s.Stats.ToDB(&dest.Stats)
|
ID: s.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Stats.ToDB(&setting.Stats)
|
||||||
|
|
||||||
|
*dest = setting
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db"
|
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db"
|
||||||
@@ -22,6 +23,19 @@ type Setup struct {
|
|||||||
Worlds []*World `json:"worlds"`
|
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 {
|
func (s *Setup) ToDB(dest *db.Setup) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
@@ -39,11 +53,11 @@ func (s *Setup) ToDB(dest *db.Setup) bool {
|
|||||||
PackageWarningsToDB(&dest.PackageWarnings, s.PackageWarnings)
|
PackageWarningsToDB(&dest.PackageWarnings, s.PackageWarnings)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &dest.Languages, s.Languages)
|
CopySliceToDBParallel(&wg, &dest.Languages, s.Languages)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Modules, s.Modules)
|
CopySliceToDBParallel(&wg, &dest.Modules, s.Modules)
|
||||||
go CopySliceToDBParallel(&wg, &dest.News, s.News)
|
CopySliceToDBParallel(&wg, &dest.News, s.News)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Systems, s.Systems)
|
CopySliceToDBParallel(&wg, &dest.Systems, s.Systems)
|
||||||
go CopySliceToDBParallel(&wg, &dest.Worlds, s.Worlds)
|
CopySliceToDBParallel(&wg, &dest.Worlds, s.Worlds)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -71,8 +71,11 @@ func (s *System) ToDB(dest **db.System) bool {
|
|||||||
HasStorage: s.HasStorage,
|
HasStorage: s.HasStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
system.Scripts = make([]string, len(s.Scripts))
|
||||||
copy(system.Scripts, s.Scripts)
|
copy(system.Scripts, s.Scripts)
|
||||||
|
system.Esmodules = make([]string, len(s.Esmodules))
|
||||||
copy(system.Esmodules, s.Esmodules)
|
copy(system.Esmodules, s.Esmodules)
|
||||||
|
system.Tags = make([]string, len(s.Tags))
|
||||||
copy(system.Tags, s.Tags)
|
copy(system.Tags, s.Tags)
|
||||||
|
|
||||||
s.Compatibility.ToDB(&system.Compatibility)
|
s.Compatibility.ToDB(&system.Compatibility)
|
||||||
@@ -81,12 +84,12 @@ func (s *System) ToDB(dest **db.System) bool {
|
|||||||
s.Grid.ToDB(&system.Grid)
|
s.Grid.ToDB(&system.Grid)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &system.Authors, s.Authors)
|
CopySliceToDBParallel(&wg, &system.Authors, s.Authors)
|
||||||
go CopySliceToDBParallel(&wg, &system.Media, s.Media)
|
CopySliceToDBParallel(&wg, &system.Media, s.Media)
|
||||||
go CopySliceToDBParallel(&wg, &system.Styles, s.Styles)
|
CopySliceToDBParallel(&wg, &system.Styles, s.Styles)
|
||||||
go CopySliceToDBParallel(&wg, &system.Languages, s.Languages)
|
CopySliceToDBParallel(&wg, &system.Languages, s.Languages)
|
||||||
go CopySliceToDBParallel(&wg, &system.Packs, s.Packs)
|
CopySliceToDBParallel(&wg, &system.Packs, s.Packs)
|
||||||
go CopySliceToDBParallel(&wg, &system.PackFolders, s.PackFolders)
|
CopySliceToDBParallel(&wg, &system.PackFolders, s.PackFolders)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
*dest = system
|
*dest = system
|
||||||
|
|||||||
@@ -18,26 +18,28 @@ type Table struct {
|
|||||||
// TablesFlags any `json:"flags,omitempty"`
|
// TablesFlags any `json:"flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) ToDB(dest *db.Table) bool {
|
func (t *Table) ToDB(dest **db.Table) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = t.Name
|
table := &db.Table{
|
||||||
dest.Description = t.Description
|
Name: t.Name,
|
||||||
dest.Formula = t.Formula
|
Description: t.Description,
|
||||||
dest.ID = t.ID
|
Formula: t.Formula,
|
||||||
dest.Img = t.Img
|
ID: t.ID,
|
||||||
dest.Replacement = t.Replacement
|
Img: t.Img,
|
||||||
dest.DisplayRoll = t.DisplayRoll
|
Replacement: t.Replacement,
|
||||||
dest.Folder = t.Folder
|
DisplayRoll: t.DisplayRoll,
|
||||||
dest.Sort = t.Sort
|
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
|
return true
|
||||||
}
|
}
|
||||||
@@ -55,22 +57,27 @@ type TableResult struct {
|
|||||||
// ResultsFlags any `json:"flags"`
|
// ResultsFlags any `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TableResult) ToDB(dest *db.TableResult) bool {
|
func (t *TableResult) ToDB(dest **db.TableResult) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Type = t.Type
|
tableResult := &db.TableResult{
|
||||||
dest.Weight = t.Weight
|
Type: t.Type,
|
||||||
dest.Drawn = t.Drawn
|
Weight: t.Weight,
|
||||||
dest.ID = t.ID
|
Drawn: t.Drawn,
|
||||||
dest.Img = t.Img
|
ID: t.ID,
|
||||||
dest.Description = t.Description
|
Img: t.Img,
|
||||||
dest.Name = t.Name
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,22 +16,26 @@ type User struct {
|
|||||||
// UsersFlags any `json:"flags,omitempty"`
|
// UsersFlags any `json:"flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) ToDB(dest *db.User) bool {
|
func (u *User) ToDB(dest **db.User) bool {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.Name = u.Name
|
user := &db.User{
|
||||||
dest.Role = u.Role
|
Name: u.Name,
|
||||||
dest.ID = u.ID
|
Role: u.Role,
|
||||||
dest.Avatar = u.Avatar
|
ID: u.ID,
|
||||||
dest.Character = u.Character
|
Avatar: u.Avatar,
|
||||||
dest.Color = u.Color
|
Character: u.Character,
|
||||||
dest.Pronouns = u.Pronouns
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db"
|
"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) {
|
func OwnershipToDB(dest *[]db.OwnershipString, src map[string]int) {
|
||||||
*dest = make([]db.OwnershipString, len(src))
|
*dest = make([]db.OwnershipString, len(src))
|
||||||
|
|
||||||
@@ -33,8 +38,8 @@ func PackageWarningsToDB(dest *[]*db.PackageWarning, src map[string]PackageWarni
|
|||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for k, v := range src {
|
for k, v := range src {
|
||||||
(*dest)[i].Key = k
|
(*dest)[i] = &db.PackageWarning{Key: k}
|
||||||
v.ToDB((*dest)[i].Value)
|
v.ToDB(&(*dest)[i].Value)
|
||||||
i++
|
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) {
|
func CopySliceToDBParallel[destType any, srcType CastableToDB[destType]](wg *sync.WaitGroup, dest *[]destType, src []srcType) {
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
CopySliceToDB(dest, src)
|
CopySliceToDB(dest, src)
|
||||||
wg.Done()
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ func (w *Wall) ToDB(dest *db.Wall) bool {
|
|||||||
dest.ID = w.ID
|
dest.ID = w.ID
|
||||||
w.Threshold.ToDB(&dest.Threshold)
|
w.Threshold.ToDB(&dest.Threshold)
|
||||||
|
|
||||||
|
dest.C = make([]int, len(w.C))
|
||||||
copy(dest.C, w.C)
|
copy(dest.C, w.C)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -71,20 +71,23 @@ func (w *World) ToDB(dest **db.World) bool {
|
|||||||
HasStorage: w.HasStorage,
|
HasStorage: w.HasStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
world.Scripts = make([]string, len(w.Scripts))
|
||||||
copy(world.Scripts, w.Scripts)
|
copy(world.Scripts, w.Scripts)
|
||||||
|
world.Esmodules = make([]string, len(w.Esmodules))
|
||||||
copy(world.Esmodules, w.Esmodules)
|
copy(world.Esmodules, w.Esmodules)
|
||||||
|
world.Tags = make([]string, len(w.Tags))
|
||||||
copy(world.Tags, w.Tags)
|
copy(world.Tags, w.Tags)
|
||||||
|
|
||||||
w.Compatibility.ToDB(&world.Compatibility)
|
w.Compatibility.ToDB(&world.Compatibility)
|
||||||
w.Relationships.ToDB(&world.Relationships)
|
w.Relationships.ToDB(&world.Relationships)
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
go CopySliceToDBParallel(&wg, &world.Authors, w.Authors)
|
CopySliceToDBParallel(&wg, &world.Authors, w.Authors)
|
||||||
go CopySliceToDBParallel(&wg, &world.Media, w.Media)
|
CopySliceToDBParallel(&wg, &world.Media, w.Media)
|
||||||
go CopySliceToDBParallel(&wg, &world.Styles, w.Styles)
|
CopySliceToDBParallel(&wg, &world.Styles, w.Styles)
|
||||||
go CopySliceToDBParallel(&wg, &world.Languages, w.Languages)
|
CopySliceToDBParallel(&wg, &world.Languages, w.Languages)
|
||||||
go CopySliceToDBParallel(&wg, &world.Packs, w.Packs)
|
CopySliceToDBParallel(&wg, &world.Packs, w.Packs)
|
||||||
go CopySliceToDBParallel(&wg, &world.PackFolders, w.PackFolders)
|
CopySliceToDBParallel(&wg, &world.PackFolders, w.PackFolders)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
*dest = world
|
*dest = world
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package transport
|
package transport
|
||||||
|
|
||||||
import (
|
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/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"
|
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,22 +14,22 @@ func (tr *FoundryTransport) FillDBWithFoundryData() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
idState, err := tr.Models.FoundryState.GetIdByType(db.SetupState)
|
// idState, err := tr.Models.FoundryState.GetIdByType(db.SetupState)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode}
|
// tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode}
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
err = tr.InitWorldsData(idState)
|
// err = tr.InitWorldsData(idState)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode}
|
// tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode}
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *FoundryTransport) InitSetupData() error {
|
func (tr *FoundryTransport) InitSetupData() error {
|
||||||
tr.Models.FoundryState.DeleteAll()
|
db.DeleteAll(tr.DB)
|
||||||
tr.Models.FoundryState.DeleteAllSeq()
|
db.DeleteAllSeq(tr.DB)
|
||||||
for k := range requests.PathToSetupState {
|
for k := range requests.PathToSetupState {
|
||||||
err := tr.InsertJsonDataToDB(k)
|
err := tr.InsertJsonDataToDB(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -51,48 +51,51 @@ func (tr *FoundryTransport) InsertJsonDataToDB(statePath string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
foundryStateJson, err := json.ParseSetupModel(msgJson)
|
foundryStateJson, err := json.ParseSetup(msgJson)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
foundryStateDb := foundryStateJson.GetFoundryStateDB(requests.PathToSetupState[statePath])
|
tr.Logger.Info("Setup data received")
|
||||||
err = tr.Models.FoundryState.Insert(foundryStateDb)
|
|
||||||
|
var foundryStateDb db.Setup
|
||||||
|
foundryStateJson.ToDB(&foundryStateDb)
|
||||||
|
err = foundryStateDb.Insert(tr.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *FoundryTransport) InitWorldsData(idState int64) error {
|
// func (tr *FoundryTransport) InitWorldsData(idState int64) error {
|
||||||
worlds, err := tr.Models.FoundryState.GetWorlds(idState)
|
// worlds, err := tr.Models.FoundryState.GetWorlds(idState)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
tr.Logger.Debug("Worlds", "len", len(worlds))
|
// tr.Logger.Debug("Worlds", "len", len(worlds))
|
||||||
|
|
||||||
for i := range worlds {
|
// for i := range worlds {
|
||||||
worldName := worlds[i].TextId
|
// worldName := worlds[i].TextId
|
||||||
tr.InitWorldData(worldName)
|
// tr.InitWorldData(worldName)
|
||||||
_, err = tr.Http.PostReturnToSetup()
|
// _, err = tr.Http.PostReturnToSetup()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (tr *FoundryTransport) InitWorldData(worldName string) error {
|
// func (tr *FoundryTransport) InitWorldData(worldName string) error {
|
||||||
tr.Logger.Debug("World name", "name", worldName)
|
// tr.Logger.Debug("World name", "name", worldName)
|
||||||
err := tr.LaunchWorld(worldName)
|
// err := tr.LaunchWorld(worldName)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
for k := range requests.PathToWorldState {
|
// for k := range requests.PathToWorldState {
|
||||||
err := tr.InsertJsonDataToDB(k)
|
// err := tr.InsertJsonDataToDB(k)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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/requests"
|
||||||
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types"
|
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@@ -26,7 +25,8 @@ type FoundryTransport struct {
|
|||||||
IsAuth bool
|
IsAuth bool
|
||||||
IsLogin bool
|
IsLogin bool
|
||||||
|
|
||||||
Models *db.Models
|
// Models *db.Models
|
||||||
|
DB *sqlx.DB
|
||||||
IsDbInit bool
|
IsDbInit bool
|
||||||
|
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
@@ -47,7 +47,7 @@ func NewFoundryTransport(dbConn *sqlx.DB, logger *slog.Logger, httpConfig *reque
|
|||||||
ReconnectNumMax: 1,
|
ReconnectNumMax: 1,
|
||||||
ReconnectNum: 0,
|
ReconnectNum: 0,
|
||||||
|
|
||||||
Models: db.NewModels(dbConn),
|
DB: dbConn,
|
||||||
IsDbInit: false,
|
IsDbInit: false,
|
||||||
|
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
|
|||||||
Reference in New Issue
Block a user