From e0d54ac46df00a0fad53577a10168a8f12955641 Mon Sep 17 00:00:00 2001 From: Masahiko AMANO Date: Mon, 6 Jan 2025 00:33:49 +0300 Subject: [PATCH] init(backend): add database interaction functions --- backend/db/db.go | 166 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 backend/db/db.go diff --git a/backend/db/db.go b/backend/db/db.go new file mode 100644 index 0000000..671d648 --- /dev/null +++ b/backend/db/db.go @@ -0,0 +1,166 @@ +package db + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/H1K0/SkazaNull/models" + "github.com/jackc/pgx/v5/pgxpool" +) + +var ConnPool *pgxpool.Pool + +func InitDB(connString string) error { + poolConfig, err := pgxpool.ParseConfig(connString) + if err != nil { + return fmt.Errorf("error while parsing connection string: %w", err) + } + + poolConfig.MaxConns = 10 + poolConfig.MinConns = 0 + poolConfig.MaxConnLifetime = time.Hour + poolConfig.HealthCheckPeriod = 30 * time.Second + + ConnPool, err = pgxpool.NewWithConfig(context.Background(), poolConfig) + if err != nil { + return fmt.Errorf("error while initializing DB connections pool: %w", err) + } + return nil +} + +//#region User + +func Authorize(ctx context.Context, login string, password string) (user models.User, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM user_auth($1, $2)", login, password) + err = row.Scan(&user.ID, &user.Name, &user.Login, &user.Role, &user.TelegramID) + return +} + +func UpdateUserName(ctx context.Context, user_id string, new_name string) (user models.User, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM user_update($1, $2)", user_id, new_name) + err = row.Scan(&user.ID, &user.Name, &user.Login, &user.Role, &user.TelegramID) + return +} + +func UpdateUserLogin(ctx context.Context, user_id string, new_login string) (user models.User, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM user_update($1, NULL, $2)", user_id, new_login) + err = row.Scan(&user.ID, &user.Name, &user.Login, &user.Role, &user.TelegramID) + return +} + +func UpdateUserTelegramID(ctx context.Context, user_id string, new_telegram_id int64) (user models.User, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM user_update($1, NULL, NULL, $2)", user_id, new_telegram_id) + err = row.Scan(&user.ID, &user.Name, &user.Login, &user.Role, &user.TelegramID) + return +} + +func UpdateUserPassword(ctx context.Context, user_id string, new_password string) (user models.User, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM user_update($1, NULL, NULL, NULL, $2)", user_id, new_password) + err = row.Scan(&user.ID, &user.Name, &user.Login, &user.Role, &user.TelegramID) + return +} + +//#endregion User + +//#region Quote + +func QuotesGet(ctx context.Context, user_id string, filter string, sort string, limit int, offset int) (quotes []models.Quote, err error) { + query := "SELECT * FROM quotes_get($1) WHERE position($2 in text)>0 OR position($2 in author)>0" + if sort == "random" { + query += " ORDER BY random()" + } else if sort != "" { + sort_options := strings.Split(sort, ",") + query += " ORDER BY " + for i, sort_option := range sort_options { + sort_order := sort_option[:1] + sort_field := sort_option[1:] + switch sort_order { + case "+": + sort_order = "ASC" + case "-": + sort_order = "DESC" + default: + err = fmt.Errorf("invalid sorting parameter: %q", sort) + return + } + switch sort_field { + case "text": + fallthrough + case "author": + fallthrough + case "datetime": + fallthrough + case "creator.name": + sort_field = strings.ReplaceAll(sort_field, ".", "_") + default: + err = fmt.Errorf("unknown sorting field: %q", sort_field) + return + } + if i > 0 { + query += ", " + } + query += fmt.Sprintf("%s %s", sort_field, sort_order) + } + } + if limit >= 0 { + query += fmt.Sprintf(" LIMIT %d", limit) + } + if offset > 0 { + query += fmt.Sprintf(" OFFSET %d", offset) + } + rows, err := ConnPool.Query(ctx, query, user_id, filter) + if err != nil { + err = fmt.Errorf("error while getting quotes: %w", err) + return + } + for rows.Next() { + var quote models.Quote + err = rows.Scan("e.ID, "e.Text, "e.Author, "e.Datetime, "e.Creator.ID, "e.Creator.Name, "e.Creator.Login, "e.Creator.Role, "e.Creator.TelegramID) + if err != nil { + err = fmt.Errorf("error while fetching quotes: %w", err) + return + } + quotes = append(quotes, quote) + } + err = rows.Err() + return +} + +func QuoteGet(ctx context.Context, user_id string, quote_id string) (quote models.Quote, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM quote_get($1, $2)", user_id, quote_id) + err = row.Scan("e.ID, "e.Text, "e.Author, "e.Datetime, "e.Creator.ID, "e.Creator.Name, "e.Creator.Login, "e.Creator.Role, "e.Creator.TelegramID) + return +} + +func QuoteAdd(ctx context.Context, user_id string, text string, author string, datetime time.Time) (quote models.Quote, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM quote_add($1, $2, $3, $4)", user_id, text, author, datetime) + err = row.Scan("e.ID, "e.Text, "e.Author, "e.Datetime, "e.Creator.ID, "e.Creator.Name, "e.Creator.Login, "e.Creator.Role, "e.Creator.TelegramID) + return +} + +func QuoteUpdateText(ctx context.Context, user_id string, quote_id string, new_text string) (quote models.Quote, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM quote_get($1, $2, $3)", user_id, quote_id, new_text) + err = row.Scan("e.ID, "e.Text, "e.Author, "e.Datetime, "e.Creator.ID, "e.Creator.Name, "e.Creator.Login, "e.Creator.Role, "e.Creator.TelegramID) + return +} + +func QuoteUpdateAuthor(ctx context.Context, user_id string, quote_id string, new_author string) (quote models.Quote, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM quote_get($1, $2, NULL, $3)", user_id, quote_id, new_author) + err = row.Scan("e.ID, "e.Text, "e.Author, "e.Datetime, "e.Creator.ID, "e.Creator.Name, "e.Creator.Login, "e.Creator.Role, "e.Creator.TelegramID) + return +} + +func QuoteUpdateDatetime(ctx context.Context, user_id string, quote_id string, new_datetime time.Time) (quote models.Quote, err error) { + row := ConnPool.QueryRow(ctx, "SELECT * FROM quote_get($1, $2, NULL, NULL, $3)", user_id, quote_id, new_datetime) + err = row.Scan("e.ID, "e.Text, "e.Author, "e.Datetime, "e.Creator.ID, "e.Creator.Name, "e.Creator.Login, "e.Creator.Role, "e.Creator.TelegramID) + return +} + +func QuoteDelete(ctx context.Context, user_id string, quote_id string) (err error) { + _, err = ConnPool.Exec(ctx, "CALL quote_delete($1, $2)", user_id, quote_id) + return +} + +//#endregion Quote