package postgres import ( "slices" "time" "git.tek.govt.hu/dowerx/chat/server/model" "git.tek.govt.hu/dowerx/chat/server/util" "github.com/jmoiron/sqlx" ) type MessageDAO struct { pgDAO } // Create a new message func (d MessageDAO) Create(message model.Message) (int, *util.ChatError) { rows, err := d.db.NamedQuery(`insert into "message" ("sender_id", "channel_id", "time", "content") values (:sender_id, :channel_id, :time, :content) returning "id"`, &message) if err != nil { return 0, util.MakeError(err, util.DATABASE_QUERY_FAULT) } if !rows.Next() { return 0, &util.ChatError{Message: "failed to insert new message", Code: util.DATABASE_QUERY_FAULT} } var id int if rows.Scan(&id) != nil { return 0, &util.ChatError{Message: "failed to return new message id", Code: util.DATABASE_QUERY_FAULT} } return int(id), util.MakeError(err, util.DATABASE_QUERY_FAULT) } // Read returns a message by ID func (d MessageDAO) Read(id int) (model.Message, *util.ChatError) { message := model.Message{} var rows *sqlx.Rows var err error rows, err = d.db.NamedQuery(`select * from "message" where "id" = $1`, id) if err != nil { return message, util.MakeError(err, util.DATABASE_QUERY_FAULT) } defer rows.Close() if !rows.Next() { return message, &util.ChatError{Message: "", Code: util.NOT_FOUND} } err = rows.StructScan(&message) return message, util.MakeError(err, util.DATABASE_QUERY_FAULT) } // List all messages in channel by ID or name func (d MessageDAO) List(channel model.Channel, from time.Time, limit int) ([]model.Message, *util.ChatError) { type queryInfo struct { ID int `db:"id"` Name string `db:"name"` From time.Time `db:"from"` Limit int `db:"limit"` } var rows *sqlx.Rows var err error if channel.ID != 0 { rows, err = d.db.NamedQuery( `select "m"."id" as "id", "u"."username" as "sender_name", "m"."channel_id" as "channel_id", "m"."time" as "time", "m"."content" as "content" from "message" as "m" inner join "user" "u" on "u"."id" = "m"."sender_id" where "m"."channel_id" = :id and "m"."time" < :from order by "time" desc limit :limit`, &queryInfo{ID: channel.ID, From: from, Limit: limit}) } else { rows, err = d.db.NamedQuery( `select "m"."id" as "id", "u"."username" as "sender_name", "m"."channel_id" as "channel_id", "m"."time" as "time", "m"."content" as "content" from "message" as "m" inner join "user" "u" on "u"."id" = "m"."sender_id" inner join "channel" "c" on "c"."id" = "m"."channel_id" where "c"."name" = :name and "m"."time" < :from order by "time" desc limit :limit`, &queryInfo{Name: channel.Name, From: from, Limit: limit}) } if err != nil { return nil, util.MakeError(err, util.DATABASE_QUERY_FAULT) } defer rows.Close() messages := make([]model.Message, 0) for rows.Next() { message := model.Message{} err = rows.StructScan(&message) if err != nil { break } messages = append(messages, message) } slices.Reverse(messages) return messages, util.MakeError(err, util.DATABASE_QUERY_FAULT) } // Update the contents and time of a Message with the given ID func (d MessageDAO) Update(message model.Message) *util.ChatError { _, err := d.db.NamedExec(`update "message" set "content" = :content, "time" = :time where "id" = :id`, &message) return util.MakeError(err, util.DATABASE_QUERY_FAULT) } // Delete a message by ID func (d MessageDAO) Delete(id int) *util.ChatError { var err error _, err = d.db.NamedExec(`delete from "message" where "id" = $1`, id) return util.MakeError(err, util.DATABASE_QUERY_FAULT) } func MakeMessageDAO() (MessageDAO, *util.ChatError) { dao := MessageDAO{} conn, err := getDatabase() if err != nil { return dao, err } dao.db = conn return dao, nil }