mirror of
https://github.com/lus/pasty.git
synced 2023-08-10 21:13:09 +03:00
Implement working postgres driver
This commit is contained in:
@ -1,13 +1,13 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/lus/pasty/internal/config"
|
||||
"github.com/lus/pasty/internal/shared"
|
||||
"github.com/lus/pasty/internal/storage/file"
|
||||
"github.com/lus/pasty/internal/storage/mongodb"
|
||||
"github.com/lus/pasty/internal/storage/postgres"
|
||||
"github.com/lus/pasty/internal/storage/s3"
|
||||
)
|
||||
|
||||
@ -48,8 +48,7 @@ func GetDriver(storageType shared.StorageType) (Driver, error) {
|
||||
case shared.StorageTypeFile:
|
||||
return new(file.FileDriver), nil
|
||||
case shared.StorageTypePostgres:
|
||||
// TODO: Implement Postgres driver
|
||||
return nil, errors.New("TODO")
|
||||
return new(postgres.PostgresDriver), nil
|
||||
case shared.StorageTypeMongoDB:
|
||||
return new(mongodb.MongoDBDriver), nil
|
||||
case shared.StorageTypeS3:
|
||||
|
@ -0,0 +1,5 @@
|
||||
begin;
|
||||
|
||||
drop table if exists "pastes";
|
||||
|
||||
commit;
|
@ -0,0 +1,12 @@
|
||||
begin;
|
||||
|
||||
create table if not exists "pastes" (
|
||||
"id" text not null,
|
||||
"content" text not null,
|
||||
"deletionToken" text not null,
|
||||
"created" bigint not null,
|
||||
"autoDelete" boolean not null,
|
||||
primary key ("id")
|
||||
);
|
||||
|
||||
commit;
|
119
internal/storage/postgres/postgres_driver.go
Normal file
119
internal/storage/postgres/postgres_driver.go
Normal file
@ -0,0 +1,119 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
_ "github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
"github.com/jackc/pgx/v4"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"github.com/johejo/golang-migrate-extra/source/iofs"
|
||||
"github.com/lus/pasty/internal/config"
|
||||
"github.com/lus/pasty/internal/shared"
|
||||
)
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var migrations embed.FS
|
||||
|
||||
// PostgresDriver represents the Postgres storage driver
|
||||
type PostgresDriver struct {
|
||||
pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
// Initialize initializes the Postgres storage driver
|
||||
func (driver *PostgresDriver) Initialize() error {
|
||||
pool, err := pgxpool.Connect(context.Background(), config.Current.Postgres.DSN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := iofs.New(migrations, "migrations")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
migrator, err := migrate.NewWithSourceInstance("iofs", source, config.Current.Postgres.DSN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := migrator.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||
return err
|
||||
}
|
||||
|
||||
driver.pool = pool
|
||||
return nil
|
||||
}
|
||||
|
||||
// Terminate terminates the Postgres storage driver
|
||||
func (driver *PostgresDriver) Terminate() error {
|
||||
driver.pool.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListIDs returns a list of all existing paste IDs
|
||||
func (driver *PostgresDriver) ListIDs() ([]string, error) {
|
||||
query := "SELECT id FROM pastes"
|
||||
|
||||
rows, err := driver.pool.Query(context.Background(), query)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
var ids []string
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// Get loads a paste
|
||||
func (driver *PostgresDriver) Get(id string) (*shared.Paste, error) {
|
||||
query := "SELECT * FROM pastes WHERE id = $1"
|
||||
|
||||
row := driver.pool.QueryRow(context.Background(), query, id)
|
||||
|
||||
paste := new(shared.Paste)
|
||||
if err := row.Scan(&paste.ID, &paste.Content, &paste.DeletionToken, &paste.Created, &paste.AutoDelete); err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return paste, nil
|
||||
}
|
||||
|
||||
// Save saves a paste
|
||||
func (driver *PostgresDriver) Save(paste *shared.Paste) error {
|
||||
query := "INSERT INTO pastes VALUES ($1, $2, $3, $4, $5)"
|
||||
|
||||
_, err := driver.pool.Exec(context.Background(), query, paste.ID, paste.Content, paste.DeletionToken, paste.Created, paste.AutoDelete)
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete deletes a paste
|
||||
func (driver *PostgresDriver) Delete(id string) error {
|
||||
query := "DELETE FROM pastes WHERE id = $1"
|
||||
|
||||
_, err := driver.pool.Exec(context.Background(), query, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Cleanup cleans up the expired pastes
|
||||
func (driver *PostgresDriver) Cleanup() (int, error) {
|
||||
query := "DELETE FROM pastes WHERE autoDelete = true AND created < $2"
|
||||
|
||||
tag, err := driver.pool.Exec(context.Background(), query, time.Now().Add(-config.Current.AutoDelete.Lifetime).Unix())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(tag.RowsAffected()), nil
|
||||
}
|
Reference in New Issue
Block a user