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 }