diff --git a/internal/db/connection.go b/internal/db/connection.go new file mode 100644 index 0000000..ae0f329 --- /dev/null +++ b/internal/db/connection.go @@ -0,0 +1,78 @@ +package db + +import ( + "database/sql" + "fmt" + "log" + + _ "github.com/lib/pq" +) + +const ( + host = "202.46.28.160" + port = 45432 + user = "5803024005" + password = "pw5803024005" + dbname = "tgs01_5803024005" +) + +var DB *sql.DB + +func InitDB() { + psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) + + var err error + DB, err = sql.Open("postgres", psqlconn) + if err != nil { + log.Fatal("Failed to open database connection:", err) + } + + // Test the connection + err = DB.Ping() + if err != nil { + log.Fatal("Failed to ping database:", err) + } + + log.Println("Database connection established successfully") + + // Create tables if they don't exist + createTables() +} + +func createTables() { + // Create Groups table + createGroupsTable := ` + CREATE TABLE IF NOT EXISTS "Groups" ( + "GroupID" SERIAL PRIMARY KEY, + "GroupName" VARCHAR(255) NOT NULL + );` + + _, err := DB.Exec(createGroupsTable) + if err != nil { + log.Fatal("Failed to create Groups table:", err) + } + + // Create Tasks table + createTasksTable := ` + CREATE TABLE IF NOT EXISTS "Tasks" ( + "TaskID" SERIAL PRIMARY KEY, + "TaskName" VARCHAR(255) NOT NULL, + "TaskDescription" TEXT, + "GroupID" INTEGER REFERENCES "Groups"("GroupID") ON DELETE CASCADE, + "IsDone" BOOLEAN DEFAULT FALSE, + "CreatedAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP + );` + + _, err = DB.Exec(createTasksTable) + if err != nil { + log.Fatal("Failed to create Tasks table:", err) + } + + log.Println("Database tables created/verified successfully") +} + +func CheckError(err error) { + if err != nil { + panic(err) + } +} diff --git a/internal/db/group_queries.go b/internal/db/group_queries.go new file mode 100644 index 0000000..7da059c --- /dev/null +++ b/internal/db/group_queries.go @@ -0,0 +1,100 @@ +package db + +import ( + "database/sql" + "errors" +) + +// GetAllGroups retrieves all groups from the database +func GetAllGroups() ([]Group, error) { + var groups []Group + query := `SELECT "GroupID", "GroupName" FROM "Groups" ORDER BY "GroupID"` + + rows, err := DB.Query(query) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var group Group + err := rows.Scan(&group.GroupID, &group.GroupName) + if err != nil { + return nil, err + } + groups = append(groups, group) + } + + return groups, nil +} + +// GetGroupByID retrieves a single group by ID +func GetGroupByID(groupID int) (*Group, error) { + var group Group + query := `SELECT "GroupID", "GroupName" FROM "Groups" WHERE "GroupID" = $1` + + err := DB.QueryRow(query, groupID).Scan(&group.GroupID, &group.GroupName) + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.New("group not found") + } + return nil, err + } + + return &group, nil +} + +// CreateGroup creates a new group in the database +func CreateGroup(groupName string) (*Group, error) { + var group Group + query := `INSERT INTO "Groups" ("GroupName") VALUES ($1) RETURNING "GroupID", "GroupName"` + + err := DB.QueryRow(query, groupName).Scan(&group.GroupID, &group.GroupName) + if err != nil { + return nil, err + } + + return &group, nil +} + +// UpdateGroup updates an existing group +func UpdateGroup(groupID int, groupName string) error { + query := `UPDATE "Groups" SET "GroupName" = $1 WHERE "GroupID" = $2` + + result, err := DB.Exec(query, groupName, groupID) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + + if rowsAffected == 0 { + return errors.New("group not found") + } + + return nil +} + +// DeleteGroup deletes a group from the database +func DeleteGroup(groupID int) error { + query := `DELETE FROM "Groups" WHERE "GroupID" = $1` + + result, err := DB.Exec(query, groupID) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + + if rowsAffected == 0 { + return errors.New("group not found") + } + + return nil +} diff --git a/internal/db/models.go b/internal/db/models.go new file mode 100644 index 0000000..c6f7a98 --- /dev/null +++ b/internal/db/models.go @@ -0,0 +1,19 @@ +package db + +import ( + "time" +) + +type Group struct { + GroupID int `json:"group_id"` + GroupName string `json:"group_name"` +} + +type Task struct { + TaskID int `json:"task_id"` + TaskName string `json:"task_name"` + TaskDescription *string `json:"task_description,omitempty"` + GroupID int `json:"group_id"` + IsDone bool `json:"is_done"` + CreatedAt time.Time `json:"created_at"` +} diff --git a/internal/db/task_queries.go b/internal/db/task_queries.go new file mode 100644 index 0000000..279daae --- /dev/null +++ b/internal/db/task_queries.go @@ -0,0 +1,155 @@ +package db + +import ( + "database/sql" + "errors" +) + +// GetAllTasks retrieves all tasks from the database +func GetAllTasks() ([]Task, error) { + var tasks []Task + query := `SELECT "TaskID", "TaskName", "TaskDescription", "GroupID", "IsDone", "CreatedAt" + FROM "Tasks" ORDER BY "CreatedAt" DESC` + + rows, err := DB.Query(query) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var task Task + err := rows.Scan(&task.TaskID, &task.TaskName, &task.TaskDescription, + &task.GroupID, &task.IsDone, &task.CreatedAt) + if err != nil { + return nil, err + } + tasks = append(tasks, task) + } + + return tasks, nil +} + +// GetTasksByGroupID retrieves all tasks for a specific group +func GetTasksByGroupID(groupID int) ([]Task, error) { + var tasks []Task + query := `SELECT "TaskID", "TaskName", "TaskDescription", "GroupID", "IsDone", "CreatedAt" + FROM "Tasks" WHERE "GroupID" = $1 ORDER BY "CreatedAt" DESC` + + rows, err := DB.Query(query, groupID) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var task Task + err := rows.Scan(&task.TaskID, &task.TaskName, &task.TaskDescription, + &task.GroupID, &task.IsDone, &task.CreatedAt) + if err != nil { + return nil, err + } + tasks = append(tasks, task) + } + + return tasks, nil +} + +// GetTaskByID retrieves a single task by ID +func GetTaskByID(taskID int) (*Task, error) { + var task Task + query := `SELECT "TaskID", "TaskName", "TaskDescription", "GroupID", "IsDone", "CreatedAt" + FROM "Tasks" WHERE "TaskID" = $1` + + err := DB.QueryRow(query, taskID).Scan(&task.TaskID, &task.TaskName, + &task.TaskDescription, &task.GroupID, + &task.IsDone, &task.CreatedAt) + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.New("task not found") + } + return nil, err + } + + return &task, nil +} + +// CreateTask creates a new task in the database +func CreateTask(taskName string, taskDescription *string, groupID int) (*Task, error) { + var task Task + query := `INSERT INTO "Tasks" ("TaskName", "TaskDescription", "GroupID") + VALUES ($1, $2, $3) RETURNING "TaskID", "TaskName", "TaskDescription", "GroupID", "IsDone", "CreatedAt"` + + err := DB.QueryRow(query, taskName, taskDescription, groupID). + Scan(&task.TaskID, &task.TaskName, &task.TaskDescription, + &task.GroupID, &task.IsDone, &task.CreatedAt) + if err != nil { + return nil, err + } + + return &task, nil +} + +// UpdateTask updates an existing task +func UpdateTask(taskID int, taskName string, taskDescription *string) error { + query := `UPDATE "Tasks" SET "TaskName" = $1, "TaskDescription" = $2 + WHERE "TaskID" = $3` + + result, err := DB.Exec(query, taskName, taskDescription, taskID) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + + if rowsAffected == 0 { + return errors.New("task not found") + } + + return nil +} + +// MarkTaskDone marks a task as completed +func MarkTaskDone(taskID int) error { + query := `UPDATE "Tasks" SET "IsDone" = true WHERE "TaskID" = $1` + + result, err := DB.Exec(query, taskID) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + + if rowsAffected == 0 { + return errors.New("task not found") + } + + return nil +} + +// DeleteTask deletes a task from the database +func DeleteTask(taskID int) error { + query := `DELETE FROM "Tasks" WHERE "TaskID" = $1` + + result, err := DB.Exec(query, taskID) + if err != nil { + return err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + + if rowsAffected == 0 { + return errors.New("task not found") + } + + return nil +}