first db support

This commit is contained in:
Marco Realacci 2022-11-17 16:22:48 +01:00
parent 441e28c5ac
commit 492c712835
7 changed files with 171 additions and 19 deletions

15
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,15 @@
{
// Usare IntelliSense per informazioni sui possibili attributi.
// Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.
// Per altre informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "./cmd/webapi"
}
]
}

View file

@ -256,15 +256,9 @@ paths:
username: username:
$ref: "#/components/schemas/name" $ref: "#/components/schemas/name"
followers: followers:
type: array $ref: "#/components/schemas/followers_n"
description: Array of users that the user is following.
items:
$ref: "#/components/schemas/uid_name"
following: following:
type: array $ref: "#/components/schemas/following_n"
description: Array of users that are following the user.
items:
$ref: "#/components/schemas/uid_name"
photos: photos:
$ref: "#/components/schemas/user_photo_stream" $ref: "#/components/schemas/user_photo_stream"
'404': '404':

View file

@ -55,11 +55,78 @@ func New(db *sql.DB) (AppDatabase, error) {
return nil, errors.New("database is required when building a AppDatabase") return nil, errors.New("database is required when building a AppDatabase")
} }
// Check if table exists. If not, the database is empty, and we need to create the structure // Check if tables exist. If not, the database is empty, and we need to create the structure
var tableName string var tableName string
err := db.QueryRow(`SELECT name FROM sqlite_master WHERE type='table' AND name='example_table';`).Scan(&tableName) err := db.QueryRow(`SELECT name FROM sqlite_master WHERE type='table' AND name='users';`).Scan(&tableName) //todo: check for all the tables
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
sqlStmt := `CREATE TABLE example_table (id INTEGER NOT NULL PRIMARY KEY, name TEXT);` sqlStmt := `CREATE TABLE "users" (
"uid" TEXT NOT NULL,
"name" TEXT NOT NULL UNIQUE,
PRIMARY KEY("uid")
)` //todo: one query is enough! Why do I need to do this?
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err)
}
sqlStmt = `CREATE TABLE "follows" (
"follower" TEXT NOT NULL,
"followed" TEXT NOT NULL,
FOREIGN KEY("follower") REFERENCES "users"("uid") ON UPDATE CASCADE,
FOREIGN KEY("followed") REFERENCES "users"("uid") ON UPDATE CASCADE,
PRIMARY KEY("follower","followed")
)`
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err)
}
sqlStmt = `CREATE TABLE "bans" (
"user" TEXT NOT NULL,
"ban" TEXT NOT NULL,
FOREIGN KEY("user") REFERENCES "users"("uid") ON UPDATE CASCADE,
FOREIGN KEY("ban") REFERENCES "users"("uid") ON UPDATE CASCADE,
PRIMARY KEY("user","ban")
)`
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err)
}
sqlStmt = `CREATE TABLE "photos" (
"user" TEXT NOT NULL,
"id" INTEGER NOT NULL,
"date" TEXT NOT NULL,
FOREIGN KEY("user") REFERENCES "users"("uid") ON UPDATE CASCADE,
PRIMARY KEY("id" AUTOINCREMENT)
)`
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err)
}
sqlStmt = `CREATE TABLE "comments" (
"user" TEXT NOT NULL,
"photo" INTEGER NOT NULL,
"id" INTEGER NOT NULL,
"comment" TEXT NOT NULL,
"date" TEXT NOT NULL,
FOREIGN KEY("user") REFERENCES "users"("uid"),
PRIMARY KEY("id" AUTOINCREMENT),
FOREIGN KEY("photo") REFERENCES "photos"("id")
);`
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err)
}
sqlStmt = `CREATE TABLE "likes" (
"user" TEXT NOT NULL,
"photo_id" INTEGER NOT NULL,
FOREIGN KEY("user") REFERENCES "users"("uid") ON UPDATE CASCADE,
FOREIGN KEY("photo_id") REFERENCES "photos"("id") ON UPDATE CASCADE,
PRIMARY KEY("user","photo_id")
)`
_, err = db.Exec(sqlStmt)
if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err)
}
sqlStmt = `PRAGMA foreign_keys = ON`
_, err = db.Exec(sqlStmt) _, err = db.Exec(sqlStmt)
if err != nil { if err != nil {
return nil, fmt.Errorf("error creating database structure: %w", err) return nil, fmt.Errorf("error creating database structure: %w", err)

View file

@ -0,0 +1,53 @@
package database
import "time"
type Photo struct {
ID int64
Likes int64
Comments int64
}
type UserProfile struct {
UID string
Name string
Following []string
Followers []string
Photos []Photo
}
// Post a new photo
func (db *appdbimpl) PostPhoto(uid string) (int64, error) {
res, err := db.c.Exec(`INSERT INTO "photos" ("user", "date") VALUES (?, ?)`, uid, time.Now().Format(time.RFC3339))
if err != nil {
return 0, err
}
id, err := res.LastInsertId()
if err != nil {
return 0, err
}
return id, nil
}
// Get user profile, including username, followers, following, and photos
func (db *appdbimpl) GetUserProfile(uid string) (*UserProfile, error) {
// Get user info
var name string
err := db.c.QueryRow(`SELECT "name" FROM "users" WHERE "uid" = ?`, uid).Scan(&name)
if err != nil {
return nil, err
}
// Get followers
}
// Like a photo
func (db *appdbimpl) LikePhoto(uid string, photo int64) error {
_, err := db.c.Exec(`INSERT INTO "likes" ("user", "photo_id") VALUES (?, ?)`, uid, photo)
return err
}
// Unlike a photo
func (db *appdbimpl) UnlikePhoto(uid string, photo int64) error {
_, err := db.c.Exec(`DELETE FROM "likes" WHERE "user" = ? AND "photo_id" = ?`, uid, photo)
return err
}

View file

@ -0,0 +1,31 @@
package database
// Create a new user
func (db *appdbimpl) CreateUser(uid string, name string) error {
_, err := db.c.Exec(`INSERT INTO "users" ("uid", "name") VALUES (?, ?)`, uid, name)
return err
}
// Follow a user
func (db *appdbimpl) FollowUser(uid string, follow string) error {
_, err := db.c.Exec(`INSERT INTO "follows" ("follower", "followed") VALUES (?, ?)`, uid, follow)
return err
}
// Unfollow a user
func (db *appdbimpl) UnfollowUser(uid string, unfollow string) error {
_, err := db.c.Exec(`DELETE FROM "follows" WHERE "follower" = ? AND "followed" = ?`, uid, unfollow)
return err
} //todo: should return boolean or something similar
// Ban a user
func (db *appdbimpl) BanUser(uid string, ban string) error {
_, err := db.c.Exec(`INSERT INTO "bans" ("user", "ban") VALUES (?, ?)`, uid, ban)
return err
}
// Unban a user
func (db *appdbimpl) UnbanUser(uid string, unban string) error {
_, err := db.c.Exec(`DELETE FROM "bans" WHERE "user" = ? AND "ban" = ?`, uid, unban)
return err
}

View file

@ -1,8 +0,0 @@
package database
// GetName is an example that shows you how to query data
func (db *appdbimpl) GetName() (string, error) {
var name string
err := db.c.QueryRow("SELECT name FROM example_table WHERE id=1").Scan(&name)
return name, err
}

BIN
wasa.db Normal file

Binary file not shown.