package repository import ( "context" "fmt" "steam_analyzer/internal/domain" "steam_analyzer/pkg/postgresql" "github.com/google/uuid" ) type PostgresDB struct { conn postgresql.PGXPool } func NewPostgresDB(conn postgresql.PGXPool) *PostgresDB { return &PostgresDB{ conn: conn, } } func (db PostgresDB) InitDatabaseTables(ctx context.Context) error { createTable := ` CREATE TABLE IF NOT EXISTS item ( id UUID PRIMARY KEY, name TEXT, class_id TEXT UNIQUE NOT NULL, game_id INTEGER NOT NULL, type_id INTEGER );` _, err := db.conn.Exec(ctx, createTable) if err != nil { return err } createTable = ` CREATE TABLE IF NOT EXISTS item_history ( item_id UUID REFERENCES item(id), price REAL, count INTEGER, date TIMESTAMPTZ NOT NULL, PRIMARY KEY (item_id, date) );` _, err = db.conn.Exec(ctx, createTable) if err != nil { return err } return nil } func (db PostgresDB) AddItem(ctx context.Context, item domain.DBItem) error { query := ` INSERT INTO item (id, name, class_id, game_id) VALUES ($1, $2, $3, $4) ` _, err := db.conn.Exec(ctx, query, item.ID, item.Name, item.ClassID, item.GameID, ) if err != nil { return err } return nil } func (db PostgresDB) AddItemHistory(ctx context.Context, dbItemHistory domain.DBItemHistory) error { query := ` INSERT INTO item_history (item_id, price, count, date) VALUES ($1, $2, $3, $4) ` _, err := db.conn.Exec(ctx, query, dbItemHistory.ItemID, dbItemHistory.Price, dbItemHistory.Count, dbItemHistory.Date, ) if err != nil { return err } return nil } func (db PostgresDB) GetItemByClassID(ctx context.Context, classID string) (*domain.SteamItem, error) { query := ` SELECT id, name, class_id FROM item WHERE class_id = $1 ` row := db.conn.QueryRow(ctx, query, classID) var steamItem domain.SteamItem err := row.Scan( &steamItem.ID, &steamItem.Name, &steamItem.ClassID, ) if err != nil { return nil, err } return &steamItem, nil } func (db PostgresDB) GetItemPriceHistoryByID(ctx context.Context, itemID uuid.UUID, limit int, offset int) ([]domain.ItemPriceHistory, error) { query := ` SELECT price, count, date FROM item_history WHERE item_id = $1 ORDER BY date DESC LIMIT $2 OFFSET $3 ` var itemPriceHistory []domain.ItemPriceHistory rows, err := db.conn.Query(ctx, query, itemID, limit, offset, ) if err != nil { return nil, err } for rows.Next() { var steamItemPriceHistory domain.ItemPriceHistory err := rows.Scan( &steamItemPriceHistory.Price, &steamItemPriceHistory.Count, &steamItemPriceHistory.Date, ) if err != nil { fmt.Println("error while iterating rows", err) continue } itemPriceHistory = append(itemPriceHistory, steamItemPriceHistory) } return itemPriceHistory, nil } func (db PostgresDB) GetItemsWithLastPriceByName(ctx context.Context, name string) ([]ItemWithLastPrice, error) { query := ` SELECT class_id, name, price, last_date FROM item JOIN ( SELECT item_id, MAX(price) AS price, MAX(date) AS last_date FROM item_history GROUP BY item_id ) as last_prices ON item.id = last_prices.item_id WHERE LOWER(name) like $1 ORDER BY last_date DESC; ` rows, err := db.conn.Query(ctx, query, "%"+name+"%", ) if err != nil { return nil, err } var itemsWithLastPrice []ItemWithLastPrice var itemWithLastPrice ItemWithLastPrice for rows.Next() { err := rows.Scan( &itemWithLastPrice.ClassID, &itemWithLastPrice.Name, &itemWithLastPrice.Price, &itemWithLastPrice.Date, ) if err != nil { fmt.Println("error while scaning row", err) continue } itemsWithLastPrice = append(itemsWithLastPrice, itemWithLastPrice) } return itemsWithLastPrice, nil }