answerer/dal/dal.go

256 lines
5.7 KiB
Go

package dal
import (
"context"
"database/sql"
_ "embed"
"encoding/json"
"fmt"
"gitea.pena/SQuiz/answerer/dal/sqlcgen"
"gitea.pena/SQuiz/answerer/model"
_ "github.com/ClickHouse/clickhouse-go"
"github.com/google/uuid"
"github.com/lib/pq"
_ "github.com/lib/pq"
"time"
)
type DAL struct {
pool *sql.DB
queries *sqlcgen.Queries
}
func New(ctx context.Context, cred string) (*DAL, error) {
pool, err := sql.Open("postgres", cred)
if err != nil {
return nil, err
}
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
if err := pool.PingContext(timeoutCtx); err != nil {
return nil, err
}
queries := sqlcgen.New(pool)
return &DAL{
pool: pool,
queries: queries,
}, nil
}
func (d *DAL) Close(ctx context.Context) error {
err := d.pool.Close()
if err != nil {
return err
}
return nil
}
func (d *DAL) GetQuizByQid(ctx context.Context, qid string) (model.Quiz, error) {
_, err := uuid.Parse(qid)
if err != nil {
return model.Quiz{}, err
}
fmt.Println("QUID", `
SELECT * FROM quiz
WHERE
deleted = false AND
archived = false AND
status = 'start' AND
qid = $1;
`)
rows, err := d.pool.QueryContext(ctx, `
SELECT * FROM quiz
WHERE
deleted = false AND
archived = false AND
(status = 'start' OR status = 'ai') AND
qid = $1;
`, qid)
if err != nil {
return model.Quiz{}, err
}
defer rows.Close()
if !rows.Next() {
return model.Quiz{}, rows.Err()
}
var piece model.Quiz
pIds := pq.Int32Array{}
if err := rows.Scan(
&piece.Id,
&piece.Qid,
&piece.AccountId,
&piece.Deleted,
&piece.Archived,
&piece.Fingerprinting,
&piece.Repeatable,
&piece.NotePrevented,
&piece.MailNotifications,
&piece.UniqueAnswers,
&piece.Super,
&piece.GroupId,
&piece.Name,
&piece.Description,
&piece.Config,
&piece.Status,
&piece.Limit,
&piece.DueTo,
&piece.TimeOfPassing,
&piece.Pausable,
&piece.Version,
&piece.VersionComment,
&pIds,
&piece.CreatedAt,
&piece.UpdatedAt,
&piece.QuestionsCount,
&piece.PassedCount,
&piece.AverageTime,
&piece.SessionCount,
&piece.GigaChat,
); err != nil {
return model.Quiz{}, err
}
piece.ParentIds = pIds
return piece, nil
}
func (d *DAL) GetQuestionListByIDs(ctx context.Context, ids []int32) ([]model.Question, error) {
rows, err := d.queries.GetQuestionListByIDs(ctx, ids)
if err != nil {
return nil, err
}
var questions []model.Question
for _, row := range rows {
question := model.Question{
Id: uint64(row.ID),
QuizId: uint64(row.QuizID),
Title: row.Title,
Description: row.Description.String,
Type: string(row.Questiontype.([]byte)),
Required: row.Required.Bool,
Deleted: row.Deleted.Bool,
Page: int(row.Page.Int16),
Content: row.Content.String,
Version: int(row.Version.Int16),
ParentIds: row.ParentIds,
CreatedAt: row.CreatedAt.Time,
UpdatedAt: row.UpdatedAt.Time,
Auditory: row.Auditory,
}
questions = append(questions, question)
}
return questions, nil
}
func (d *DAL) CreateQuestion(ctx context.Context, record *model.Question) (uint64, error) {
params := sqlcgen.InsertQuestionParams{
QuizID: int64(record.QuizId),
Title: record.Title,
Description: sql.NullString{String: record.Description, Valid: true},
Questiontype: record.Type,
Required: sql.NullBool{Bool: record.Required, Valid: true},
Page: sql.NullInt16{Int16: int16(record.Page), Valid: true},
Content: sql.NullString{String: record.Content, Valid: true},
ParentIds: record.ParentIds,
UpdatedAt: sql.NullTime{Time: time.Now(), Valid: true},
Session: record.Session,
Auditory: record.Auditory,
}
data, err := d.queries.InsertQuestion(ctx, params)
if err != nil {
return 0, err
}
record.Id = uint64(data.ID)
record.CreatedAt = data.CreatedAt.Time
record.UpdatedAt = data.UpdatedAt.Time
return record.Id, nil
}
func (d *DAL) CreateAnswers(ctx context.Context, answers []model.Answer, session, fp string, quizID uint64) ([]model.Answer, []error) {
var (
createdAnswers []model.Answer
errs []error
)
tx, err := d.pool.BeginTx(ctx, nil)
if err != nil {
return nil, []error{err}
}
for _, ans := range answers {
if ans.Utm == nil {
ans.Utm = make(model.UTMSavingMap)
}
utmJSON, err := json.Marshal(ans.Utm)
if err != nil {
return nil, []error{err}
}
params := sqlcgen.InsertAnswersParams{
Content: sql.NullString{String: ans.Content, Valid: true},
QuizID: int64(quizID),
QuestionID: int64(ans.QuestionId),
Fingerprint: sql.NullString{String: fp, Valid: true},
Session: sql.NullString{String: session, Valid: true},
Result: sql.NullBool{Bool: ans.Result, Valid: true},
Email: ans.Email,
Device: ans.Device,
DeviceType: ans.DeviceType,
Ip: ans.IP,
Browser: ans.Browser,
Os: ans.OS,
Start: ans.Start,
Utm: utmJSON,
Version: ans.Version,
}
row, err := d.queries.InsertAnswers(ctx, params)
createdAnswer := model.Answer{
Id: uint64(row.ID),
Content: row.Content.String,
QuizId: uint64(row.QuizID),
QuestionId: uint64(row.QuestionID),
Fingerprint: row.Fingerprint.String,
Session: row.Session.String,
Result: row.Result.Bool,
New: row.New.Bool,
Email: row.Email,
DeviceType: row.DeviceType,
Device: row.Device,
OS: row.Os,
Browser: row.Browser,
IP: row.Ip,
Start: row.Start,
Version: row.Version,
}
if err != nil {
errs = append(errs, err)
} else {
createdAnswers = append(createdAnswers, createdAnswer)
}
}
err = tx.Commit()
if err != nil {
errs = append(errs, err)
return nil, errs
}
return createdAnswers, errs
}