Compare commits
3 Commits
ad3c77b40e
...
761babfa1a
| Author | SHA1 | Date | |
|---|---|---|---|
| 761babfa1a | |||
| 59eacd6bc5 | |||
| 5ac528be05 |
@ -1,49 +1,50 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
)
|
)
|
||||||
|
|
||||||
var connPool *pgxpool.Pool
|
var connPool *pgxpool.Pool
|
||||||
|
|
||||||
func InitDB(connString string) error {
|
func InitDB(connString string) error {
|
||||||
poolConfig, err := pgxpool.ParseConfig(connString)
|
poolConfig, err := pgxpool.ParseConfig(connString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while parsing connection string: %w", err)
|
return fmt.Errorf("error while parsing connection string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
poolConfig.MaxConns = 100
|
poolConfig.MaxConns = 100
|
||||||
poolConfig.MinConns = 0
|
poolConfig.MinConns = 0
|
||||||
poolConfig.MaxConnLifetime = time.Hour
|
poolConfig.MaxConnLifetime = time.Hour
|
||||||
poolConfig.HealthCheckPeriod = 30 * time.Second
|
poolConfig.HealthCheckPeriod = 30 * time.Second
|
||||||
|
|
||||||
connPool, err = pgxpool.NewWithConfig(context.Background(), poolConfig)
|
connPool, err = pgxpool.NewWithConfig(context.Background(), poolConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while initializing DB connections pool: %w", err)
|
return fmt.Errorf("error while initializing DB connections pool: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func transaction(ctx context.Context, handler func(pgx.Tx) (statusCode int, err error)) (statusCode int, err error) {
|
func transaction(handler func(context.Context, pgx.Tx) (statusCode int, err error)) (statusCode int, err error) {
|
||||||
tx, err := connPool.Begin(ctx)
|
ctx := context.Background()
|
||||||
if err != nil {
|
tx, err := connPool.Begin(ctx)
|
||||||
statusCode = http.StatusInternalServerError
|
if err != nil {
|
||||||
return
|
statusCode = http.StatusInternalServerError
|
||||||
}
|
return
|
||||||
statusCode, err = handler(tx)
|
}
|
||||||
if err != nil {
|
statusCode, err = handler(ctx, tx)
|
||||||
tx.Rollback(ctx)
|
if err != nil {
|
||||||
return
|
tx.Rollback(ctx)
|
||||||
}
|
return
|
||||||
err = tx.Commit(ctx)
|
}
|
||||||
if err != nil {
|
err = tx.Commit(ctx)
|
||||||
statusCode = http.StatusInternalServerError
|
if err != nil {
|
||||||
}
|
statusCode = http.StatusInternalServerError
|
||||||
return
|
}
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|||||||
53
backend/db/utils.go
Normal file
53
backend/db/utils.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Convert "filter" URL param to SQL "WHERE" condition
|
||||||
|
func filterToSQL(filter string) (sql string, statusCode int, err error) {
|
||||||
|
// filterTokens := strings.Split(string(filter), ";")
|
||||||
|
sql = "(true)"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert "sort" URL param to SQL "ORDER BY"
|
||||||
|
func sortToSQL(sort string) (sql string, statusCode int, err error) {
|
||||||
|
if sort == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sortOptions := strings.Split(sort, ",")
|
||||||
|
sql = " ORDER BY "
|
||||||
|
for i, sortOption := range sortOptions {
|
||||||
|
sortOrder := sortOption[:1]
|
||||||
|
sortColumn := sortOption[1:]
|
||||||
|
// parse sorting order marker
|
||||||
|
switch sortOrder {
|
||||||
|
case "+":
|
||||||
|
sortOrder = "ASC"
|
||||||
|
case "-":
|
||||||
|
sortOrder = "DESC"
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid sorting order mark: %q", sortOrder)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// validate sorting column
|
||||||
|
var n int
|
||||||
|
n, err = strconv.Atoi(sortColumn)
|
||||||
|
if err != nil || n < 0 {
|
||||||
|
err = fmt.Errorf("invalid sorting column: %q", sortColumn)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// add sorting option to query
|
||||||
|
if i > 0 {
|
||||||
|
sql += ","
|
||||||
|
}
|
||||||
|
sql += fmt.Sprintf("%s %s NULLS LAST", sortColumn, sortOrder)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@ -1,71 +1,75 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
type User struct {
|
|
||||||
Name string `json:"name"`
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
IsAdmin bool `json:"is_admin"`
|
)
|
||||||
}
|
|
||||||
|
type User struct {
|
||||||
type MIME struct {
|
Name string `json:"name"`
|
||||||
Name string `json:"name"`
|
IsAdmin bool `json:"is_admin"`
|
||||||
Extension string `json:"extension"`
|
}
|
||||||
}
|
|
||||||
|
type MIME struct {
|
||||||
type Category struct {
|
Name string `json:"name"`
|
||||||
ID string `json:"id"`
|
Extension string `json:"extension"`
|
||||||
Name string `json:"name"`
|
}
|
||||||
Color string `json:"color"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
type Category struct {
|
||||||
Creator User `json:"creator"`
|
ID string `json:"id"`
|
||||||
}
|
Name string `json:"name"`
|
||||||
|
Color pgtype.Text `json:"color"`
|
||||||
type File struct {
|
CreatedAt time.Time `json:"created_at"`
|
||||||
ID string `json:"id"`
|
Creator User `json:"creator"`
|
||||||
Name string `json:"name"`
|
}
|
||||||
MIME MIME `json:"mime"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
type File struct {
|
||||||
Creator User `json:"creator"`
|
ID string `json:"id"`
|
||||||
}
|
Name pgtype.Text `json:"name"`
|
||||||
|
MIME MIME `json:"mime"`
|
||||||
type Tag struct {
|
CreatedAt time.Time `json:"created_at"`
|
||||||
ID string `json:"id"`
|
Creator User `json:"creator"`
|
||||||
Name string `json:"name"`
|
}
|
||||||
Color string `json:"color"`
|
|
||||||
Category Category `json:"category"`
|
type Tag struct {
|
||||||
CreatedAt time.Time `json:"created_at"`
|
ID string `json:"id"`
|
||||||
Creator User `json:"creator"`
|
Name string `json:"name"`
|
||||||
}
|
Color pgtype.Text `json:"color"`
|
||||||
|
Category Category `json:"category"`
|
||||||
type Autotag struct {
|
CreatedAt time.Time `json:"created_at"`
|
||||||
TriggerTag Tag `json:"trigger_tag"`
|
Creator User `json:"creator"`
|
||||||
AddTag Tag `json:"add_tag"`
|
}
|
||||||
IsActive bool `json:"is_active"`
|
|
||||||
}
|
type Autotag struct {
|
||||||
|
TriggerTag Tag `json:"trigger_tag"`
|
||||||
type Pool struct {
|
AddTag Tag `json:"add_tag"`
|
||||||
ID string `json:"id"`
|
IsActive bool `json:"is_active"`
|
||||||
Name string `json:"name"`
|
}
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
Creator User `json:"creator"`
|
type Pool struct {
|
||||||
}
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
type Session struct {
|
CreatedAt time.Time `json:"created_at"`
|
||||||
ID int `json:"id"`
|
Creator User `json:"creator"`
|
||||||
UserAgent string `json:"user_agent"`
|
}
|
||||||
StartedAt time.Time `json:"started_at"`
|
|
||||||
ExpiresAt time.Time `json:"expires_at"`
|
type Session struct {
|
||||||
LastActivity time.Time `json:"last_activity"`
|
ID int `json:"id"`
|
||||||
}
|
UserAgent string `json:"user_agent"`
|
||||||
|
StartedAt time.Time `json:"started_at"`
|
||||||
type Pagination struct {
|
ExpiresAt time.Time `json:"expires_at"`
|
||||||
Total int `json:"total"`
|
LastActivity time.Time `json:"last_activity"`
|
||||||
Offset int `json:"offset"`
|
}
|
||||||
Limit int `json:"limit"`
|
|
||||||
Count int `json:"count"`
|
type Pagination struct {
|
||||||
}
|
Total int `json:"total"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
type Slice[T any] struct {
|
Limit int `json:"limit"`
|
||||||
Pagination Pagination `json:"pagination"`
|
Count int `json:"count"`
|
||||||
Data []T `json:"data"`
|
}
|
||||||
}
|
|
||||||
|
type Slice[T any] struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Data []T `json:"data"`
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user