db
import "github.com/Ask-Atlas/AskAtlas/api/internal/db"
Index
- type Course
- type CourseFavorite
- type CourseFile
- type CourseLastViewed
- type CourseMember
- type CourseResource
- type CourseRole
- type CourseSection
- type DBTX
- type DeleteGuideFileParams
- type DeleteGuideResourceParams
- type DeleteStudyGuideRecommendationParams
- type DeleteStudyGuideVoteParams
- type File
- type FileDeletionStatus
- type FileFavorite
- type FileGrant
- type FileLastViewed
- type FileView
- type GetCourseRow
- type GetFileByOwnerParams
- type GetFileByOwnerRow
- type GetFileForAttachRow
- type GetFileIfViewableParams
- type GetGuideResourceAttacherParams
- type GetMembershipParams
- type GetMembershipRow
- type GetQuizByIDForUpdateRow
- type GetQuizDetailRow
- type GetQuizForUpdateWithParentStatusRow
- type GetResourceByCreatorURLParams
- type GetResourceByCreatorURLRow
- type GetStudyGuideByIDForUpdateRow
- type GetStudyGuideDetailRow
- type GetUserVoteForGuideParams
- type GranteeType
- type GuideFileAttachedParams
- type InsertFileParams
- type InsertGuideFileParams
- type InsertGuideResourceParams
- type InsertQuizAnswerOptionParams
- type InsertQuizParams
- type InsertQuizQuestionParams
- type InsertQuizRow
- type InsertStudyGuideParams
- type InsertStudyGuideRecommendationParams
- type InsertStudyGuideRecommendationRow
- type InsertStudyGuideRow
- type JoinSectionParams
- type LeaveSectionParams
- type ListCourseSectionsRow
- type ListCoursesCreatedAtAscParams
- type ListCoursesCreatedAtAscRow
- type ListCoursesCreatedAtDescParams
- type ListCoursesCreatedAtDescRow
- type ListCoursesDepartmentAscParams
- type ListCoursesDepartmentAscRow
- type ListCoursesDepartmentDescParams
- type ListCoursesDepartmentDescRow
- type ListCoursesNumberAscParams
- type ListCoursesNumberAscRow
- type ListCoursesNumberDescParams
- type ListCoursesNumberDescRow
- type ListCoursesTitleAscParams
- type ListCoursesTitleAscRow
- type ListCoursesTitleDescParams
- type ListCoursesTitleDescRow
- type ListGuideFilesRow
- type ListGuideQuizzesWithQuestionCountRow
- type ListGuideRecommendersRow
- type ListGuideResourcesRow
- type ListMyEnrollmentsParams
- type ListMyEnrollmentsRow
- type ListOwnedFilesCreatedAscParams
- type ListOwnedFilesCreatedAscRow
- type ListOwnedFilesCreatedDescParams
- type ListOwnedFilesCreatedDescRow
- type ListOwnedFilesMimeAscParams
- type ListOwnedFilesMimeAscRow
- type ListOwnedFilesMimeDescParams
- type ListOwnedFilesMimeDescRow
- type ListOwnedFilesNameAscParams
- type ListOwnedFilesNameAscRow
- type ListOwnedFilesNameDescParams
- type ListOwnedFilesNameDescRow
- type ListOwnedFilesSizeAscParams
- type ListOwnedFilesSizeAscRow
- type ListOwnedFilesSizeDescParams
- type ListOwnedFilesSizeDescRow
- type ListOwnedFilesStatusAscParams
- type ListOwnedFilesStatusAscRow
- type ListOwnedFilesStatusDescParams
- type ListOwnedFilesStatusDescRow
- type ListOwnedFilesUpdatedAscParams
- type ListOwnedFilesUpdatedAscRow
- type ListOwnedFilesUpdatedDescParams
- type ListOwnedFilesUpdatedDescRow
- type ListQuizQuestionsByQuizRow
- type ListQuizzesByStudyGuideRow
- type ListSchoolsParams
- type ListSectionMembersParams
- type ListSectionMembersRow
- type ListStudyGuidesNewestAscParams
- type ListStudyGuidesNewestAscRow
- type ListStudyGuidesNewestDescParams
- type ListStudyGuidesNewestDescRow
- type ListStudyGuidesScoreAscParams
- type ListStudyGuidesScoreAscRow
- type ListStudyGuidesScoreDescParams
- type ListStudyGuidesScoreDescRow
- type ListStudyGuidesUpdatedAscParams
- type ListStudyGuidesUpdatedAscRow
- type ListStudyGuidesUpdatedDescParams
- type ListStudyGuidesUpdatedDescRow
- type ListStudyGuidesViewsAscParams
- type ListStudyGuidesViewsAscRow
- type ListStudyGuidesViewsDescParams
- type ListStudyGuidesViewsDescRow
- type NullCourseRole
- type NullFileDeletionStatus
- type NullGranteeType
- type NullPermission
- type NullQuestionType
- type NullResourceType
- type NullUploadStatus
- type NullVoteDirection
- type Permission
- type PracticeAnswer
- type PracticeSession
- type PracticeSessionQuestion
- type Querier
- type Queries
- func New(db DBTX) *Queries
- func (q *Queries) ComputeGuideVoteScore(ctx context.Context, studyGuideID pgtype.UUID) (int64, error)
- func (q *Queries) CourseExists(ctx context.Context, id pgtype.UUID) (bool, error)
- func (q *Queries) CourseExistsForGuides(ctx context.Context, id pgtype.UUID) (bool, error)
- func (q *Queries) DeleteGuideFile(ctx context.Context, arg DeleteGuideFileParams) (int64, error)
- func (q *Queries) DeleteGuideResource(ctx context.Context, arg DeleteGuideResourceParams) (int64, error)
- func (q *Queries) DeleteStudyGuideRecommendation(ctx context.Context, arg DeleteStudyGuideRecommendationParams) (int64, error)
- func (q *Queries) DeleteStudyGuideVote(ctx context.Context, arg DeleteStudyGuideVoteParams) (int64, error)
- func (q *Queries) GetCourse(ctx context.Context, id pgtype.UUID) (GetCourseRow, error)
- func (q *Queries) GetFileByOwner(ctx context.Context, arg GetFileByOwnerParams) (GetFileByOwnerRow, error)
- func (q *Queries) GetFileForAttach(ctx context.Context, id pgtype.UUID) (GetFileForAttachRow, error)
- func (q *Queries) GetFileIfViewable(ctx context.Context, arg GetFileIfViewableParams) (File, error)
- func (q *Queries) GetGuideResourceAttacher(ctx context.Context, arg GetGuideResourceAttacherParams) (pgtype.UUID, error)
- func (q *Queries) GetMembership(ctx context.Context, arg GetMembershipParams) (GetMembershipRow, error)
- func (q *Queries) GetQuizByIDForUpdate(ctx context.Context, id pgtype.UUID) (GetQuizByIDForUpdateRow, error)
- func (q *Queries) GetQuizDetail(ctx context.Context, id pgtype.UUID) (GetQuizDetailRow, error)
- func (q *Queries) GetQuizForUpdateWithParentStatus(ctx context.Context, id pgtype.UUID) (GetQuizForUpdateWithParentStatusRow, error)
- func (q *Queries) GetResourceByCreatorURL(ctx context.Context, arg GetResourceByCreatorURLParams) (GetResourceByCreatorURLRow, error)
- func (q *Queries) GetSchool(ctx context.Context, id pgtype.UUID) (School, error)
- func (q *Queries) GetStudyGuideByIDForUpdate(ctx context.Context, id pgtype.UUID) (GetStudyGuideByIDForUpdateRow, error)
- func (q *Queries) GetStudyGuideDetail(ctx context.Context, id pgtype.UUID) (GetStudyGuideDetailRow, error)
- func (q *Queries) GetUserIDByClerkID(ctx context.Context, clerkID string) (pgtype.UUID, error)
- func (q *Queries) GetUserVoteForGuide(ctx context.Context, arg GetUserVoteForGuideParams) (VoteDirection, error)
- func (q *Queries) GuideExistsAndLive(ctx context.Context, id pgtype.UUID) (bool, error)
- func (q *Queries) GuideExistsAndLiveForQuizzes(ctx context.Context, id pgtype.UUID) (bool, error)
- func (q *Queries) GuideFileAttached(ctx context.Context, arg GuideFileAttachedParams) (bool, error)
- func (q *Queries) InsertFile(ctx context.Context, arg InsertFileParams) (File, error)
- func (q *Queries) InsertGuideFile(ctx context.Context, arg InsertGuideFileParams) (pgtype.Timestamptz, error)
- func (q *Queries) InsertGuideResource(ctx context.Context, arg InsertGuideResourceParams) error
- func (q *Queries) InsertQuiz(ctx context.Context, arg InsertQuizParams) (InsertQuizRow, error)
- func (q *Queries) InsertQuizAnswerOption(ctx context.Context, arg InsertQuizAnswerOptionParams) error
- func (q *Queries) InsertQuizQuestion(ctx context.Context, arg InsertQuizQuestionParams) (pgtype.UUID, error)
- func (q *Queries) InsertStudyGuide(ctx context.Context, arg InsertStudyGuideParams) (InsertStudyGuideRow, error)
- func (q *Queries) InsertStudyGuideRecommendation(ctx context.Context, arg InsertStudyGuideRecommendationParams) (InsertStudyGuideRecommendationRow, error)
- func (q *Queries) JoinSection(ctx context.Context, arg JoinSectionParams) (CourseMember, error)
- func (q *Queries) LeaveSection(ctx context.Context, arg LeaveSectionParams) (pgtype.UUID, error)
- func (q *Queries) ListCourseSections(ctx context.Context, courseID pgtype.UUID) ([]ListCourseSectionsRow, error)
- func (q *Queries) ListCoursesCreatedAtAsc(ctx context.Context, arg ListCoursesCreatedAtAscParams) ([]ListCoursesCreatedAtAscRow, error)
- func (q *Queries) ListCoursesCreatedAtDesc(ctx context.Context, arg ListCoursesCreatedAtDescParams) ([]ListCoursesCreatedAtDescRow, error)
- func (q *Queries) ListCoursesDepartmentAsc(ctx context.Context, arg ListCoursesDepartmentAscParams) ([]ListCoursesDepartmentAscRow, error)
- func (q *Queries) ListCoursesDepartmentDesc(ctx context.Context, arg ListCoursesDepartmentDescParams) ([]ListCoursesDepartmentDescRow, error)
- func (q *Queries) ListCoursesNumberAsc(ctx context.Context, arg ListCoursesNumberAscParams) ([]ListCoursesNumberAscRow, error)
- func (q *Queries) ListCoursesNumberDesc(ctx context.Context, arg ListCoursesNumberDescParams) ([]ListCoursesNumberDescRow, error)
- func (q *Queries) ListCoursesTitleAsc(ctx context.Context, arg ListCoursesTitleAscParams) ([]ListCoursesTitleAscRow, error)
- func (q *Queries) ListCoursesTitleDesc(ctx context.Context, arg ListCoursesTitleDescParams) ([]ListCoursesTitleDescRow, error)
- func (q *Queries) ListGuideFiles(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideFilesRow, error)
- func (q *Queries) ListGuideQuizzesWithQuestionCount(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideQuizzesWithQuestionCountRow, error)
- func (q *Queries) ListGuideRecommenders(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideRecommendersRow, error)
- func (q *Queries) ListGuideResources(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideResourcesRow, error)
- func (q *Queries) ListMyEnrollments(ctx context.Context, arg ListMyEnrollmentsParams) ([]ListMyEnrollmentsRow, error)
- func (q *Queries) ListOwnedFilesCreatedAsc(ctx context.Context, arg ListOwnedFilesCreatedAscParams) ([]ListOwnedFilesCreatedAscRow, error)
- func (q *Queries) ListOwnedFilesCreatedDesc(ctx context.Context, arg ListOwnedFilesCreatedDescParams) ([]ListOwnedFilesCreatedDescRow, error)
- func (q *Queries) ListOwnedFilesMimeAsc(ctx context.Context, arg ListOwnedFilesMimeAscParams) ([]ListOwnedFilesMimeAscRow, error)
- func (q *Queries) ListOwnedFilesMimeDesc(ctx context.Context, arg ListOwnedFilesMimeDescParams) ([]ListOwnedFilesMimeDescRow, error)
- func (q *Queries) ListOwnedFilesNameAsc(ctx context.Context, arg ListOwnedFilesNameAscParams) ([]ListOwnedFilesNameAscRow, error)
- func (q *Queries) ListOwnedFilesNameDesc(ctx context.Context, arg ListOwnedFilesNameDescParams) ([]ListOwnedFilesNameDescRow, error)
- func (q *Queries) ListOwnedFilesSizeAsc(ctx context.Context, arg ListOwnedFilesSizeAscParams) ([]ListOwnedFilesSizeAscRow, error)
- func (q *Queries) ListOwnedFilesSizeDesc(ctx context.Context, arg ListOwnedFilesSizeDescParams) ([]ListOwnedFilesSizeDescRow, error)
- func (q *Queries) ListOwnedFilesStatusAsc(ctx context.Context, arg ListOwnedFilesStatusAscParams) ([]ListOwnedFilesStatusAscRow, error)
- func (q *Queries) ListOwnedFilesStatusDesc(ctx context.Context, arg ListOwnedFilesStatusDescParams) ([]ListOwnedFilesStatusDescRow, error)
- func (q *Queries) ListOwnedFilesUpdatedAsc(ctx context.Context, arg ListOwnedFilesUpdatedAscParams) ([]ListOwnedFilesUpdatedAscRow, error)
- func (q *Queries) ListOwnedFilesUpdatedDesc(ctx context.Context, arg ListOwnedFilesUpdatedDescParams) ([]ListOwnedFilesUpdatedDescRow, error)
- func (q *Queries) ListQuizAnswerOptionsByQuiz(ctx context.Context, quizID pgtype.UUID) ([]QuizAnswerOption, error)
- func (q *Queries) ListQuizQuestionsByQuiz(ctx context.Context, quizID pgtype.UUID) ([]ListQuizQuestionsByQuizRow, error)
- func (q *Queries) ListQuizzesByStudyGuide(ctx context.Context, studyGuideID pgtype.UUID) ([]ListQuizzesByStudyGuideRow, error)
- func (q *Queries) ListSchools(ctx context.Context, arg ListSchoolsParams) ([]School, error)
- func (q *Queries) ListSectionMembers(ctx context.Context, arg ListSectionMembersParams) ([]ListSectionMembersRow, error)
- func (q *Queries) ListStudyGuidesNewestAsc(ctx context.Context, arg ListStudyGuidesNewestAscParams) ([]ListStudyGuidesNewestAscRow, error)
- func (q *Queries) ListStudyGuidesNewestDesc(ctx context.Context, arg ListStudyGuidesNewestDescParams) ([]ListStudyGuidesNewestDescRow, error)
- func (q *Queries) ListStudyGuidesScoreAsc(ctx context.Context, arg ListStudyGuidesScoreAscParams) ([]ListStudyGuidesScoreAscRow, error)
- func (q *Queries) ListStudyGuidesScoreDesc(ctx context.Context, arg ListStudyGuidesScoreDescParams) ([]ListStudyGuidesScoreDescRow, error)
- func (q *Queries) ListStudyGuidesUpdatedAsc(ctx context.Context, arg ListStudyGuidesUpdatedAscParams) ([]ListStudyGuidesUpdatedAscRow, error)
- func (q *Queries) ListStudyGuidesUpdatedDesc(ctx context.Context, arg ListStudyGuidesUpdatedDescParams) ([]ListStudyGuidesUpdatedDescRow, error)
- func (q *Queries) ListStudyGuidesViewsAsc(ctx context.Context, arg ListStudyGuidesViewsAscParams) ([]ListStudyGuidesViewsAscRow, error)
- func (q *Queries) ListStudyGuidesViewsDesc(ctx context.Context, arg ListStudyGuidesViewsDescParams) ([]ListStudyGuidesViewsDescRow, error)
- func (q *Queries) MarkFileDeleted(ctx context.Context, fileID pgtype.UUID) error
- func (q *Queries) RevokeFileGrant(ctx context.Context, arg RevokeFileGrantParams) error
- func (q *Queries) SectionInCourseExists(ctx context.Context, arg SectionInCourseExistsParams) (bool, error)
- func (q *Queries) SetFileDeletionJobID(ctx context.Context, arg SetFileDeletionJobIDParams) error
- func (q *Queries) SoftDeleteFile(ctx context.Context, arg SoftDeleteFileParams) (int64, error)
- func (q *Queries) SoftDeleteQuiz(ctx context.Context, id pgtype.UUID) error
- func (q *Queries) SoftDeleteQuizzesForGuide(ctx context.Context, studyGuideID pgtype.UUID) error
- func (q *Queries) SoftDeleteStudyGuide(ctx context.Context, id pgtype.UUID) error
- func (q *Queries) SoftDeleteUserByClerkID(ctx context.Context, clerkID string) (int64, error)
- func (q *Queries) URLAlreadyAttachedToGuide(ctx context.Context, arg URLAlreadyAttachedToGuideParams) (bool, error)
- func (q *Queries) UpdateFile(ctx context.Context, arg UpdateFileParams) (UpdateFileRow, error)
- func (q *Queries) UpdateFileStatus(ctx context.Context, arg UpdateFileStatusParams) error
- func (q *Queries) UpdateQuiz(ctx context.Context, arg UpdateQuizParams) error
- func (q *Queries) UpdateStudyGuide(ctx context.Context, arg UpdateStudyGuideParams) error
- func (q *Queries) UpsertClerkUser(ctx context.Context, arg UpsertClerkUserParams) (User, error)
- func (q *Queries) UpsertFileGrant(ctx context.Context, arg UpsertFileGrantParams) (FileGrant, error)
- func (q *Queries) UpsertResource(ctx context.Context, arg UpsertResourceParams) error
- func (q *Queries) UpsertStudyGuideVote(ctx context.Context, arg UpsertStudyGuideVoteParams) error
- func (q *Queries) ViewerCanRecommendForGuide(ctx context.Context, arg ViewerCanRecommendForGuideParams) (ViewerCanRecommendForGuideRow, error)
- func (q *Queries) WithTx(tx pgx.Tx) *Queries
- type QuestionType
- type Quiz
- type QuizAnswerOption
- type QuizQuestion
- type Resource
- type ResourceType
- type RevokeFileGrantParams
- type School
- type SectionInCourseExistsParams
- type SetFileDeletionJobIDParams
- type SoftDeleteFileParams
- type StudyGuide
- type StudyGuideFavorite
- type StudyGuideFile
- type StudyGuideLastViewed
- type StudyGuideRecommendation
- type StudyGuideResource
- type StudyGuideVote
- type URLAlreadyAttachedToGuideParams
- type UpdateFileParams
- type UpdateFileRow
- type UpdateFileStatusParams
- type UpdateQuizParams
- type UpdateStudyGuideParams
- type UploadStatus
- type UpsertClerkUserParams
- type UpsertFileGrantParams
- type UpsertResourceParams
- type UpsertStudyGuideVoteParams
- type User
- type ViewerCanRecommendForGuideParams
- type ViewerCanRecommendForGuideRow
- type VoteDirection
type Course
type Course struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type CourseFavorite
type CourseFavorite struct {
UserID pgtype.UUID `json:"user_id"`
CourseID pgtype.UUID `json:"course_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type CourseFile
type CourseFile struct {
FileID pgtype.UUID `json:"file_id"`
CourseID pgtype.UUID `json:"course_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type CourseLastViewed
type CourseLastViewed struct {
UserID pgtype.UUID `json:"user_id"`
CourseID pgtype.UUID `json:"course_id"`
ViewedAt pgtype.Timestamptz `json:"viewed_at"`
}
type CourseMember
type CourseMember struct {
UserID pgtype.UUID `json:"user_id"`
SectionID pgtype.UUID `json:"section_id"`
Role CourseRole `json:"role"`
JoinedAt pgtype.Timestamptz `json:"joined_at"`
}
type CourseResource
type CourseResource struct {
ResourceID pgtype.UUID `json:"resource_id"`
CourseID pgtype.UUID `json:"course_id"`
AttachedBy pgtype.UUID `json:"attached_by"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type CourseRole
type CourseRole string
const (
CourseRoleStudent CourseRole = "student"
CourseRoleInstructor CourseRole = "instructor"
CourseRoleTa CourseRole = "ta"
)
func (*CourseRole) Scan
func (e *CourseRole) Scan(src interface{}) error
type CourseSection
type CourseSection struct {
ID pgtype.UUID `json:"id"`
CourseID pgtype.UUID `json:"course_id"`
Term string `json:"term"`
SectionCode pgtype.Text `json:"section_code"`
InstructorName pgtype.Text `json:"instructor_name"`
StartDate pgtype.Date `json:"start_date"`
EndDate pgtype.Date `json:"end_date"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type DBTX
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
type DeleteGuideFileParams
type DeleteGuideFileParams struct {
FileID pgtype.UUID `json:"file_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type DeleteGuideResourceParams
type DeleteGuideResourceParams struct {
ResourceID pgtype.UUID `json:"resource_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type DeleteStudyGuideRecommendationParams
type DeleteStudyGuideRecommendationParams struct {
StudyGuideID pgtype.UUID `json:"study_guide_id"`
RecommendedBy pgtype.UUID `json:"recommended_by"`
}
type DeleteStudyGuideVoteParams
type DeleteStudyGuideVoteParams struct {
UserID pgtype.UUID `json:"user_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type File
type File struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
}
type FileDeletionStatus
type FileDeletionStatus string
const (
FileDeletionStatusPendingDeletion FileDeletionStatus = "pending_deletion"
FileDeletionStatusDeleted FileDeletionStatus = "deleted"
)
func (*FileDeletionStatus) Scan
func (e *FileDeletionStatus) Scan(src interface{}) error
type FileFavorite
type FileFavorite struct {
UserID pgtype.UUID `json:"user_id"`
FileID pgtype.UUID `json:"file_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type FileGrant
type FileGrant struct {
ID pgtype.UUID `json:"id"`
FileID pgtype.UUID `json:"file_id"`
GranteeType GranteeType `json:"grantee_type"`
GranteeID pgtype.UUID `json:"grantee_id"`
Permission Permission `json:"permission"`
GrantedBy pgtype.UUID `json:"granted_by"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type FileLastViewed
type FileLastViewed struct {
UserID pgtype.UUID `json:"user_id"`
FileID pgtype.UUID `json:"file_id"`
ViewedAt pgtype.Timestamptz `json:"viewed_at"`
}
type FileView
type FileView struct {
ID pgtype.UUID `json:"id"`
FileID pgtype.UUID `json:"file_id"`
UserID pgtype.UUID `json:"user_id"`
ViewedAt pgtype.Timestamptz `json:"viewed_at"`
}
type GetCourseRow
type GetCourseRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type GetFileByOwnerParams
type GetFileByOwnerParams struct {
FileID pgtype.UUID `json:"file_id"`
OwnerID pgtype.UUID `json:"owner_id"`
}
type GetFileByOwnerRow
type GetFileByOwnerRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type GetFileForAttachRow
type GetFileForAttachRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
Status UploadStatus `json:"status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
}
type GetFileIfViewableParams
type GetFileIfViewableParams struct {
FileID pgtype.UUID `json:"file_id"`
ViewerID pgtype.UUID `json:"viewer_id"`
CourseIds []pgtype.UUID `json:"course_ids"`
StudyGuideIds []pgtype.UUID `json:"study_guide_ids"`
}
type GetGuideResourceAttacherParams
type GetGuideResourceAttacherParams struct {
ResourceID pgtype.UUID `json:"resource_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type GetMembershipParams
type GetMembershipParams struct {
UserID pgtype.UUID `json:"user_id"`
SectionID pgtype.UUID `json:"section_id"`
}
type GetMembershipRow
type GetMembershipRow struct {
Role CourseRole `json:"role"`
JoinedAt pgtype.Timestamptz `json:"joined_at"`
}
type GetQuizByIDForUpdateRow
type GetQuizByIDForUpdateRow struct {
ID pgtype.UUID `json:"id"`
CreatorID pgtype.UUID `json:"creator_id"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type GetQuizDetailRow
type GetQuizDetailRow struct {
ID pgtype.UUID `json:"id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
}
type GetQuizForUpdateWithParentStatusRow
type GetQuizForUpdateWithParentStatusRow struct {
ID pgtype.UUID `json:"id"`
CreatorID pgtype.UUID `json:"creator_id"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
GuideDeletedAt pgtype.Timestamptz `json:"guide_deleted_at"`
}
type GetResourceByCreatorURLParams
type GetResourceByCreatorURLParams struct {
CreatorID pgtype.UUID `json:"creator_id"`
Url string `json:"url"`
}
type GetResourceByCreatorURLRow
type GetResourceByCreatorURLRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Url string `json:"url"`
Type ResourceType `json:"type"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type GetStudyGuideByIDForUpdateRow
type GetStudyGuideByIDForUpdateRow struct {
ID pgtype.UUID `json:"id"`
CreatorID pgtype.UUID `json:"creator_id"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type GetStudyGuideDetailRow
type GetStudyGuideDetailRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Content pgtype.Text `json:"content"`
Tags []string `json:"tags"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CourseID pgtype.UUID `json:"course_id"`
CourseDepartment string `json:"course_department"`
CourseNumber string `json:"course_number"`
CourseTitle string `json:"course_title"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
}
type GetUserVoteForGuideParams
type GetUserVoteForGuideParams struct {
StudyGuideID pgtype.UUID `json:"study_guide_id"`
ViewerID pgtype.UUID `json:"viewer_id"`
}
type GranteeType
type GranteeType string
const (
GranteeTypeUser GranteeType = "user"
GranteeTypeCourse GranteeType = "course"
GranteeTypeStudyGuide GranteeType = "study_guide"
)
func (*GranteeType) Scan
func (e *GranteeType) Scan(src interface{}) error
type GuideFileAttachedParams
type GuideFileAttachedParams struct {
FileID pgtype.UUID `json:"file_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type InsertFileParams
type InsertFileParams struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
}
type InsertGuideFileParams
type InsertGuideFileParams struct {
FileID pgtype.UUID `json:"file_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type InsertGuideResourceParams
type InsertGuideResourceParams struct {
ResourceID pgtype.UUID `json:"resource_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
AttachedBy pgtype.UUID `json:"attached_by"`
}
type InsertQuizAnswerOptionParams
type InsertQuizAnswerOptionParams struct {
QuestionID pgtype.UUID `json:"question_id"`
Text string `json:"text"`
IsCorrect bool `json:"is_correct"`
SortOrder int32 `json:"sort_order"`
}
type InsertQuizParams
type InsertQuizParams struct {
StudyGuideID pgtype.UUID `json:"study_guide_id"`
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
}
type InsertQuizQuestionParams
type InsertQuizQuestionParams struct {
QuizID pgtype.UUID `json:"quiz_id"`
Type QuestionType `json:"type"`
QuestionText string `json:"question_text"`
Hint pgtype.Text `json:"hint"`
FeedbackCorrect pgtype.Text `json:"feedback_correct"`
FeedbackIncorrect pgtype.Text `json:"feedback_incorrect"`
ReferenceAnswer pgtype.Text `json:"reference_answer"`
SortOrder int32 `json:"sort_order"`
}
type InsertQuizRow
type InsertQuizRow struct {
ID pgtype.UUID `json:"id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type InsertStudyGuideParams
type InsertStudyGuideParams struct {
CourseID pgtype.UUID `json:"course_id"`
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Content pgtype.Text `json:"content"`
Tags []string `json:"tags"`
}
type InsertStudyGuideRecommendationParams
type InsertStudyGuideRecommendationParams struct {
RecommendedBy pgtype.UUID `json:"recommended_by"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type InsertStudyGuideRecommendationRow
type InsertStudyGuideRecommendationRow struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
type InsertStudyGuideRow
type InsertStudyGuideRow struct {
ID pgtype.UUID `json:"id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type JoinSectionParams
type JoinSectionParams struct {
UserID pgtype.UUID `json:"user_id"`
SectionID pgtype.UUID `json:"section_id"`
}
type LeaveSectionParams
type LeaveSectionParams struct {
UserID pgtype.UUID `json:"user_id"`
SectionID pgtype.UUID `json:"section_id"`
}
type ListCourseSectionsRow
type ListCourseSectionsRow struct {
ID pgtype.UUID `json:"id"`
Term string `json:"term"`
SectionCode pgtype.Text `json:"section_code"`
InstructorName pgtype.Text `json:"instructor_name"`
StartDate pgtype.Date `json:"start_date"`
MemberCount int64 `json:"member_count"`
}
type ListCoursesCreatedAtAscParams
type ListCoursesCreatedAtAscParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorCreatedAt pgtype.Timestamptz `json:"cursor_created_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesCreatedAtAscRow
type ListCoursesCreatedAtAscRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesCreatedAtDescParams
type ListCoursesCreatedAtDescParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorCreatedAt pgtype.Timestamptz `json:"cursor_created_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesCreatedAtDescRow
type ListCoursesCreatedAtDescRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesDepartmentAscParams
type ListCoursesDepartmentAscParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorDepartment pgtype.Text `json:"cursor_department"`
CursorNumber pgtype.Text `json:"cursor_number"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesDepartmentAscRow
type ListCoursesDepartmentAscRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesDepartmentDescParams
type ListCoursesDepartmentDescParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorDepartment pgtype.Text `json:"cursor_department"`
CursorNumber pgtype.Text `json:"cursor_number"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesDepartmentDescRow
type ListCoursesDepartmentDescRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesNumberAscParams
type ListCoursesNumberAscParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorNumber pgtype.Text `json:"cursor_number"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesNumberAscRow
type ListCoursesNumberAscRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesNumberDescParams
type ListCoursesNumberDescParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorNumber pgtype.Text `json:"cursor_number"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesNumberDescRow
type ListCoursesNumberDescRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesTitleAscParams
type ListCoursesTitleAscParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorTitle pgtype.Text `json:"cursor_title"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesTitleAscRow
type ListCoursesTitleAscRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListCoursesTitleDescParams
type ListCoursesTitleDescParams struct {
SchoolID pgtype.UUID `json:"school_id"`
Department pgtype.Text `json:"department"`
Q pgtype.Text `json:"q"`
CursorTitle pgtype.Text `json:"cursor_title"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListCoursesTitleDescRow
type ListCoursesTitleDescRow struct {
ID pgtype.UUID `json:"id"`
SchoolID pgtype.UUID `json:"school_id"`
Department string `json:"department"`
Number string `json:"number"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SID pgtype.UUID `json:"s_id"`
SName string `json:"s_name"`
SAcronym string `json:"s_acronym"`
SCity pgtype.Text `json:"s_city"`
SState pgtype.Text `json:"s_state"`
SCountry pgtype.Text `json:"s_country"`
}
type ListGuideFilesRow
type ListGuideFilesRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
}
type ListGuideQuizzesWithQuestionCountRow
type ListGuideQuizzesWithQuestionCountRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
QuestionCount int64 `json:"question_count"`
}
type ListGuideRecommendersRow
type ListGuideRecommendersRow struct {
ID pgtype.UUID `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
type ListGuideResourcesRow
type ListGuideResourcesRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Url string `json:"url"`
Type ResourceType `json:"type"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type ListMyEnrollmentsParams
type ListMyEnrollmentsParams struct {
UserID pgtype.UUID `json:"user_id"`
Term pgtype.Text `json:"term"`
Role NullCourseRole `json:"role"`
}
type ListMyEnrollmentsRow
type ListMyEnrollmentsRow struct {
SectionID pgtype.UUID `json:"section_id"`
SectionTerm string `json:"section_term"`
SectionSectionCode pgtype.Text `json:"section_section_code"`
SectionInstructorName pgtype.Text `json:"section_instructor_name"`
CourseID pgtype.UUID `json:"course_id"`
CourseDepartment string `json:"course_department"`
CourseNumber string `json:"course_number"`
CourseTitle string `json:"course_title"`
SchoolID pgtype.UUID `json:"school_id"`
SchoolAcronym string `json:"school_acronym"`
MemberRole CourseRole `json:"member_role"`
MemberJoinedAt pgtype.Timestamptz `json:"member_joined_at"`
}
type ListOwnedFilesCreatedAscParams
type ListOwnedFilesCreatedAscParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorCreatedAt pgtype.Timestamptz `json:"cursor_created_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesCreatedAscRow
type ListOwnedFilesCreatedAscRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesCreatedDescParams
type ListOwnedFilesCreatedDescParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorCreatedAt pgtype.Timestamptz `json:"cursor_created_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesCreatedDescRow
type ListOwnedFilesCreatedDescRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesMimeAscParams
type ListOwnedFilesMimeAscParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorMimeType pgtype.Text `json:"cursor_mime_type"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesMimeAscRow
type ListOwnedFilesMimeAscRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesMimeDescParams
type ListOwnedFilesMimeDescParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorMimeType pgtype.Text `json:"cursor_mime_type"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesMimeDescRow
type ListOwnedFilesMimeDescRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesNameAscParams
type ListOwnedFilesNameAscParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorNameLower pgtype.Text `json:"cursor_name_lower"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesNameAscRow
type ListOwnedFilesNameAscRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesNameDescParams
type ListOwnedFilesNameDescParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorNameLower pgtype.Text `json:"cursor_name_lower"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesNameDescRow
type ListOwnedFilesNameDescRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesSizeAscParams
type ListOwnedFilesSizeAscParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorSize pgtype.Int8 `json:"cursor_size"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesSizeAscRow
type ListOwnedFilesSizeAscRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesSizeDescParams
type ListOwnedFilesSizeDescParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorSize pgtype.Int8 `json:"cursor_size"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesSizeDescRow
type ListOwnedFilesSizeDescRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesStatusAscParams
type ListOwnedFilesStatusAscParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorStatus NullUploadStatus `json:"cursor_status"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesStatusAscRow
type ListOwnedFilesStatusAscRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesStatusDescParams
type ListOwnedFilesStatusDescParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorStatus NullUploadStatus `json:"cursor_status"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesStatusDescRow
type ListOwnedFilesStatusDescRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesUpdatedAscParams
type ListOwnedFilesUpdatedAscParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesUpdatedAscRow
type ListOwnedFilesUpdatedAscRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListOwnedFilesUpdatedDescParams
type ListOwnedFilesUpdatedDescParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
OwnerID pgtype.UUID `json:"owner_id"`
Status NullUploadStatus `json:"status"`
MimeType pgtype.Text `json:"mime_type"`
MinSize pgtype.Int8 `json:"min_size"`
MaxSize pgtype.Int8 `json:"max_size"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
UpdatedFrom pgtype.Timestamptz `json:"updated_from"`
UpdatedTo pgtype.Timestamptz `json:"updated_to"`
Q pgtype.Text `json:"q"`
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListOwnedFilesUpdatedDescRow
type ListOwnedFilesUpdatedDescRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
S3Key string `json:"s3_key"`
Name string `json:"name"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"`
Checksum pgtype.Text `json:"checksum"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletionStatus NullFileDeletionStatus `json:"deletion_status"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
S3DeletedAt pgtype.Timestamptz `json:"s3_deleted_at"`
DeletionJobID pgtype.Text `json:"deletion_job_id"`
FavoritedAt pgtype.Timestamptz `json:"favorited_at"`
LastViewedAt pgtype.Timestamptz `json:"last_viewed_at"`
}
type ListQuizQuestionsByQuizRow
type ListQuizQuestionsByQuizRow struct {
ID pgtype.UUID `json:"id"`
Type QuestionType `json:"type"`
QuestionText string `json:"question_text"`
Hint pgtype.Text `json:"hint"`
FeedbackCorrect pgtype.Text `json:"feedback_correct"`
FeedbackIncorrect pgtype.Text `json:"feedback_incorrect"`
ReferenceAnswer pgtype.Text `json:"reference_answer"`
SortOrder int32 `json:"sort_order"`
}
type ListQuizzesByStudyGuideRow
type ListQuizzesByStudyGuideRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
QuestionCount int64 `json:"question_count"`
}
type ListSchoolsParams
type ListSchoolsParams struct {
Q pgtype.Text `json:"q"`
CursorName pgtype.Text `json:"cursor_name"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
}
type ListSectionMembersParams
type ListSectionMembersParams struct {
SectionID pgtype.UUID `json:"section_id"`
Role NullCourseRole `json:"role"`
CursorJoinedAt pgtype.Timestamptz `json:"cursor_joined_at"`
CursorUserID pgtype.UUID `json:"cursor_user_id"`
PageLimit int32 `json:"page_limit"`
}
type ListSectionMembersRow
type ListSectionMembersRow struct {
UserID pgtype.UUID `json:"user_id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Role CourseRole `json:"role"`
JoinedAt pgtype.Timestamptz `json:"joined_at"`
}
type ListStudyGuidesNewestAscParams
type ListStudyGuidesNewestAscParams struct {
CursorCreatedAt pgtype.Timestamptz `json:"cursor_created_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesNewestAscRow
type ListStudyGuidesNewestAscRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesNewestDescParams
type ListStudyGuidesNewestDescParams struct {
CursorCreatedAt pgtype.Timestamptz `json:"cursor_created_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesNewestDescRow
type ListStudyGuidesNewestDescRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesScoreAscParams
type ListStudyGuidesScoreAscParams struct {
CursorVoteScore pgtype.Int8 `json:"cursor_vote_score"`
CursorViewCount pgtype.Int8 `json:"cursor_view_count"`
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesScoreAscRow
type ListStudyGuidesScoreAscRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesScoreDescParams
type ListStudyGuidesScoreDescParams struct {
CursorVoteScore pgtype.Int8 `json:"cursor_vote_score"`
CursorViewCount pgtype.Int8 `json:"cursor_view_count"`
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesScoreDescRow
type ListStudyGuidesScoreDescRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesUpdatedAscParams
type ListStudyGuidesUpdatedAscParams struct {
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesUpdatedAscRow
type ListStudyGuidesUpdatedAscRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesUpdatedDescParams
type ListStudyGuidesUpdatedDescParams struct {
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesUpdatedDescRow
type ListStudyGuidesUpdatedDescRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesViewsAscParams
type ListStudyGuidesViewsAscParams struct {
CursorViewCount pgtype.Int8 `json:"cursor_view_count"`
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesViewsAscRow
type ListStudyGuidesViewsAscRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type ListStudyGuidesViewsDescParams
type ListStudyGuidesViewsDescParams struct {
CursorViewCount pgtype.Int8 `json:"cursor_view_count"`
CursorUpdatedAt pgtype.Timestamptz `json:"cursor_updated_at"`
CursorID pgtype.UUID `json:"cursor_id"`
PageLimit int32 `json:"page_limit"`
CourseID pgtype.UUID `json:"course_id"`
Q pgtype.Text `json:"q"`
Tags []string `json:"tags"`
}
type ListStudyGuidesViewsDescRow
type ListStudyGuidesViewsDescRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Tags []string `json:"tags"`
CourseID pgtype.UUID `json:"course_id"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatorFirstName string `json:"creator_first_name"`
CreatorLastName string `json:"creator_last_name"`
VoteScore int64 `json:"vote_score"`
IsRecommended bool `json:"is_recommended"`
QuizCount int64 `json:"quiz_count"`
}
type NullCourseRole
type NullCourseRole struct {
CourseRole CourseRole `json:"course_role"`
Valid bool `json:"valid"` // Valid is true if CourseRole is not NULL
}
func (*NullCourseRole) Scan
func (ns *NullCourseRole) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullCourseRole) Value
func (ns NullCourseRole) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullFileDeletionStatus
type NullFileDeletionStatus struct {
FileDeletionStatus FileDeletionStatus `json:"file_deletion_status"`
Valid bool `json:"valid"` // Valid is true if FileDeletionStatus is not NULL
}
func (*NullFileDeletionStatus) Scan
func (ns *NullFileDeletionStatus) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullFileDeletionStatus) Value
func (ns NullFileDeletionStatus) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullGranteeType
type NullGranteeType struct {
GranteeType GranteeType `json:"grantee_type"`
Valid bool `json:"valid"` // Valid is true if GranteeType is not NULL
}
func (*NullGranteeType) Scan
func (ns *NullGranteeType) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullGranteeType) Value
func (ns NullGranteeType) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullPermission
type NullPermission struct {
Permission Permission `json:"permission"`
Valid bool `json:"valid"` // Valid is true if Permission is not NULL
}
func (*NullPermission) Scan
func (ns *NullPermission) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullPermission) Value
func (ns NullPermission) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullQuestionType
type NullQuestionType struct {
QuestionType QuestionType `json:"question_type"`
Valid bool `json:"valid"` // Valid is true if QuestionType is not NULL
}
func (*NullQuestionType) Scan
func (ns *NullQuestionType) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullQuestionType) Value
func (ns NullQuestionType) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullResourceType
type NullResourceType struct {
ResourceType ResourceType `json:"resource_type"`
Valid bool `json:"valid"` // Valid is true if ResourceType is not NULL
}
func (*NullResourceType) Scan
func (ns *NullResourceType) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullResourceType) Value
func (ns NullResourceType) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullUploadStatus
type NullUploadStatus struct {
UploadStatus UploadStatus `json:"upload_status"`
Valid bool `json:"valid"` // Valid is true if UploadStatus is not NULL
}
func (*NullUploadStatus) Scan
func (ns *NullUploadStatus) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullUploadStatus) Value
func (ns NullUploadStatus) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type NullVoteDirection
type NullVoteDirection struct {
VoteDirection VoteDirection `json:"vote_direction"`
Valid bool `json:"valid"` // Valid is true if VoteDirection is not NULL
}
func (*NullVoteDirection) Scan
func (ns *NullVoteDirection) Scan(value interface{}) error
Scan implements the Scanner interface.
func (NullVoteDirection) Value
func (ns NullVoteDirection) Value() (driver.Value, error)
Value implements the driver Valuer interface.
type Permission
type Permission string
const (
PermissionView Permission = "view"
PermissionShare Permission = "share"
PermissionDelete Permission = "delete"
)
func (*Permission) Scan
func (e *Permission) Scan(src interface{}) error
type PracticeAnswer
type PracticeAnswer struct {
ID pgtype.UUID `json:"id"`
SessionID pgtype.UUID `json:"session_id"`
QuestionID pgtype.UUID `json:"question_id"`
UserAnswer pgtype.Text `json:"user_answer"`
IsCorrect pgtype.Bool `json:"is_correct"`
Verified bool `json:"verified"`
AnsweredAt pgtype.Timestamptz `json:"answered_at"`
}
type PracticeSession
type PracticeSession struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
QuizID pgtype.UUID `json:"quiz_id"`
StartedAt pgtype.Timestamptz `json:"started_at"`
CompletedAt pgtype.Timestamptz `json:"completed_at"`
TotalQuestions int32 `json:"total_questions"`
CorrectAnswers int32 `json:"correct_answers"`
}
type PracticeSessionQuestion
type PracticeSessionQuestion struct {
ID pgtype.UUID `json:"id"`
SessionID pgtype.UUID `json:"session_id"`
QuestionID pgtype.UUID `json:"question_id"`
SortOrder int32 `json:"sort_order"`
}
type Querier
type Querier interface {
// Recomputes the guide's vote_score from study_guide_votes. Returned
// as int64 to match the wire shape on CastVoteResponse. Run after
// the upsert in the same logical request so the response reflects the
// post-mutation state.
ComputeGuideVoteScore(ctx context.Context, studyGuideID pgtype.UUID) (int64, error)
// Single-row existence probe used by join/leave to disambiguate the
// "Course not found" 404 from the "Section not found" 404 the spec
// requires (see ASK-132 / ASK-138).
CourseExists(ctx context.Context, id pgtype.UUID) (bool, error)
// Single-row probe used by the list handler to disambiguate "course
// missing" (404) from "course exists but has no guides" (200 empty
// array). Separate from courses.CourseExists only because sqlc-generated
// queriers are per-file; the predicate is identical.
CourseExistsForGuides(ctx context.Context, id pgtype.UUID) (bool, error)
// Removes the (file_id, study_guide_id) join row. Returns rows-
// affected so the service can detect the concurrency-race case
// (0 rows = a parallel detach already removed it, still maps to
// 404 to match the get-then-delete contract). The file row is
// preserved -- it may be attached to other guides + courses, and
// the spec explicitly forbids cascading the file delete from a
// single detach.
DeleteGuideFile(ctx context.Context, arg DeleteGuideFileParams) (int64, error)
// Removes the join row only. The resources row is preserved -- it
// may be attached to other guides + courses, and the spec
// explicitly forbids cascading the resource delete from a single
// detach. Returns rows-affected so the service can detect
// already-detached races (0 rows -> 404) vs success (1 row -> nil).
DeleteGuideResource(ctx context.Context, arg DeleteGuideResourceParams) (int64, error)
// Hard-delete the (viewer, guide) recommendation row. Returns the
// rows-affected count so the service can distinguish "viewer never
// recommended this guide" (0 rows -> 404 'Recommendation not found')
// from a successful delete (1 row -> 204). The guide-existence +
// role gate runs FIRST in the service so 'Study guide not found' /
// 403 win over 'Recommendation not found' when applicable.
DeleteStudyGuideRecommendation(ctx context.Context, arg DeleteStudyGuideRecommendationParams) (int64, error)
// Hard-delete the (viewer, guide) vote row (ASK-141). Returns the
// rows-affected count so the service can distinguish "no existing
// vote" (0 rows -> 404 'Vote not found') from a successful delete
// (1 row -> 204). The guide-existence check happens BEFORE this
// runs in the service so a missing guide doesn't leak through as
// "vote not found".
DeleteStudyGuideVote(ctx context.Context, arg DeleteStudyGuideVoteParams) (int64, error)
GetCourse(ctx context.Context, id pgtype.UUID) (GetCourseRow, error)
// Fetches a file only if it belongs to the given user and has not been soft-deleted.
// Returns sql.ErrNoRows if not found or already in a deletion state.
GetFileByOwner(ctx context.Context, arg GetFileByOwnerParams) (GetFileByOwnerRow, error)
// File-side gate for AttachFile (ASK-121). Returns the file's
// ownership + status fields so the service can choose 403 (not
// owner) vs 404 (missing / not 'complete' / soft-deleted) without
// a second round trip. Filters NOTHING -- the service inspects
// status + deleted_at + deletion_status to decide vs returning
// pre-filtered for "is the row attachable" since the messages
// differ (403 vs 404) and we want to give the right one.
//
// The columns mirror files.GetFileByOwner -- this is intentional;
// the cross-package read keeps the service layer aware of file
// ownership without reaching into the files package.
GetFileForAttach(ctx context.Context, id pgtype.UUID) (GetFileForAttachRow, error)
GetFileIfViewable(ctx context.Context, arg GetFileIfViewableParams) (File, error)
// Lookup for DetachResource (ASK-116). Returns the attached_by user
// on the join row so the service can run the dual-authz check
// (viewer is guide creator OR viewer is attached_by). sql.ErrNoRows
// maps to 'Resource attachment not found' 404 -- the resource may
// exist but isn't attached to THIS guide.
GetGuideResourceAttacher(ctx context.Context, arg GetGuideResourceAttacherParams) (pgtype.UUID, error)
// Single-row membership lookup powering the per-section
// enrolled/not-enrolled probe (ASK-148). Returns sql.ErrNoRows when the
// viewer is not a member; the service translates that into the 200
// {enrolled:false} response, NOT a 404.
GetMembership(ctx context.Context, arg GetMembershipParams) (GetMembershipRow, error)
// Locked SELECT used at the start of DeleteQuiz (ASK-102) and
// UpdateQuiz (ASK-153). SELECT FOR UPDATE prevents two concurrent
// mutators from racing on the same row -- one wins with 204/200,
// the other sees the post-mutation state in its tx snapshot and
// returns 404. Filters NOTHING -- the service inspects deleted_at
// + creator_id to choose 404 vs 403 vs proceed (mirrors
// studyguides.GetStudyGuideByIDForUpdate).
GetQuizByIDForUpdate(ctx context.Context, id pgtype.UUID) (GetQuizByIDForUpdateRow, error)
// Load the quiz row + privacy-floor creator info for the detail
// payload. The study guide is NOT joined back -- the caller already
// knows the study_guide_id (it's in the URL on POST and on the
// quiz row itself). Excludes soft-deleted quizzes (deleted_at IS
// NULL), soft-deleted creators (u.deleted_at IS NULL), and
// soft-deleted parent guides (sg.deleted_at IS NULL) so a hydration
// that races with a parent-cascade soft-delete reports 'not found'
// rather than rendering an orphaned quiz.
GetQuizDetail(ctx context.Context, id pgtype.UUID) (GetQuizDetailRow, error)
// Locked SELECT used by UpdateQuiz (ASK-153). Like
// GetQuizByIDForUpdate but also joins to the parent study guide
// so the service can enforce the "parent guide must be live"
// gate (AC6) inside the same transaction without a second round
// trip. Locks ONLY the quiz row (FOR UPDATE OF q) -- the parent
// guide is read-only at this site and we don't want to hold a
// write lock on it for the duration of the quiz update.
//
// Filters NOTHING -- the service inspects the four fields to
// choose 404 (missing quiz / deleted quiz / deleted guide) vs
// 403 (not creator) vs proceed.
GetQuizForUpdateWithParentStatus(ctx context.Context, id pgtype.UUID) (GetQuizForUpdateWithParentStatusRow, error)
// Lookup pair for UpsertResource above. Returns the resources row
// the viewer owns for this URL; always succeeds because the upsert
// runs immediately before this in the same tx (either the INSERT
// wrote the row or it was already there).
GetResourceByCreatorURL(ctx context.Context, arg GetResourceByCreatorURLParams) (GetResourceByCreatorURLRow, error)
GetSchool(ctx context.Context, id pgtype.UUID) (School, error)
// Locked SELECT used at the start of DeleteStudyGuide. SELECT FOR
// UPDATE prevents concurrent deletes from racing on the same guide
// (one wins with 204, the other sees the row already-deleted in its
// transaction's snapshot and returns 404). Filters NOTHING -- the
// service inspects deleted_at + creator_id to choose 404 vs 403 vs
// proceed.
GetStudyGuideByIDForUpdate(ctx context.Context, id pgtype.UUID) (GetStudyGuideByIDForUpdateRow, error)
// The detail endpoint's main query (ASK-114). Returns the guide's own
// columns + a compact course payload + a compact creator payload
// + two inline aggregates as subqueries:
// * vote_score -- SUM(up/down votes)
// * is_recommended -- EXISTS in study_guide_recommendations
//
// The viewer's own vote (user_vote) ships in a separate query
// (GetUserVoteForGuide) because sqlc does not infer nullable output
// columns from LEFT JOIN / subquery expressions on enum-typed columns
// -- it reads the schema's NOT NULL constraint and types the output
// non-nullable. An extra round trip is cheaper than fighting sqlc's
// type inference; the PRD's "batching as separate queries" guidance
// explicitly allows it.
//
// Soft-delete invariants:
// * sg.deleted_at IS NULL -- excludes deleted guides (→ 404)
// * u.deleted_at IS NULL -- creator must be live (ASK-143 convention)
//
// Privacy floor: no email, no clerk_id. Creator exposes only
// id/first_name/last_name.
GetStudyGuideDetail(ctx context.Context, id pgtype.UUID) (GetStudyGuideDetailRow, error)
GetUserIDByClerkID(ctx context.Context, clerkID string) (pgtype.UUID, error)
// Returns the viewer's own vote on the guide, or sql.ErrNoRows when
// the viewer has not voted. The service maps ErrNoRows to a nil
// user_vote in the response (JSON null, not omitted).
GetUserVoteForGuide(ctx context.Context, arg GetUserVoteForGuideParams) (VoteDirection, error)
// Live-presence probe used by both vote endpoints. Returns TRUE only
// when the guide row exists AND is not soft-deleted. The vote service
// gates on this before the upsert/delete so a missing-or-deleted
// guide returns 404 with a clear message rather than e.g. trampling
// through to the SQL layer and surfacing a generic FK error.
GuideExistsAndLive(ctx context.Context, id pgtype.UUID) (bool, error)
// Quizzes write + read queries (ASK-150 / ASK-136).
//
// The create flow is wrapped in a single InTx in the service layer:
// InsertQuiz -> N x InsertQuizQuestion -> M x InsertQuizAnswerOption.
// A failure at any step rolls everything back, so a partial quiz can
// never be observed by another reader.
//
// The post-insert hydration runs OUTSIDE the transaction (commit
// happens first) using GetQuizDetail + ListQuizQuestionsByQuiz +
// ListQuizAnswerOptionsByQuiz. The two-list fan-out matches the
// studyguides detail pattern -- mapping options back onto questions
// happens in Go because pgx returns flat rowsets and the question
// count is small (<=100 per quiz).
//
// Privacy floor on the creator payload mirrors studyguides: id +
// first_name + last_name only. No email, no clerk_id.
// Live-presence probe for the create-quiz endpoint. Returns TRUE
// only when the guide row exists AND is not soft-deleted. The
// studyguides package has an identical query (GuideExistsAndLive);
// duplicated here so the quizzes service can stay decoupled from
// the studyguides Repository interface (sqlc generates queriers
// per package -- both call the same row but live in different
// generated method tables).
GuideExistsAndLiveForQuizzes(ctx context.Context, id pgtype.UUID) (bool, error)
// Lookup for DetachFile (ASK-124). Returns TRUE when the (file,
// guide) join row exists. Used as the 404 short-circuit before the
// delete fires -- we want a clean 'File attachment not found' rather
// than relying on DeleteGuideFile :execrows which can't distinguish
// 'never existed' from 'concurrent detach happened first'.
GuideFileAttached(ctx context.Context, arg GuideFileAttachedParams) (bool, error)
InsertFile(ctx context.Context, arg InsertFileParams) (File, error)
// Creates the (file_id, study_guide_id) join row. Uses ON CONFLICT
// DO NOTHING + RETURNING so a duplicate attach surfaces as
// sql.ErrNoRows in Go, which the service maps to a 409 'File is
// already attached to this study guide'. Same pattern as
// recommendations + JoinSection.
//
// No attached_by column on this join table (unlike
// study_guide_resources) -- file ownership is determined from
// files.user_id instead, and the dual-authz check on detach
// compares against guide.creator_id + file.user_id.
InsertGuideFile(ctx context.Context, arg InsertGuideFileParams) (pgtype.Timestamptz, error)
// Creates the (resource_id, study_guide_id, attached_by) join row.
// The PK is (resource_id, study_guide_id) so a same-resource-and-guide
// duplicate raises a unique_violation -- but the user-facing 409
// conflict on a duplicate URL is detected EARLIER by
// URLAlreadyAttachedToGuide (which catches across resource rows
// with the same URL but different creators). This INSERT's PK
// failure mode is the narrow concurrency-race: two attachers slip
// through the pre-check between query 1 and query 4.
InsertGuideResource(ctx context.Context, arg InsertGuideResourceParams) error
// Insert a new quiz row. Returns the columns the service needs to
// build the QuizDetailResponse without an extra round trip on the
// write side -- the read-side hydration still happens via
// GetQuizDetail because the creator's first_name + last_name come
// from a join to users (and would inflate this RETURNING clause).
InsertQuiz(ctx context.Context, arg InsertQuizParams) (InsertQuizRow, error)
// Insert one option row. The service has already validated that
// exactly one option per MCQ has is_correct=true; for true-false
// questions the service synthesises two options (`True` + `False`)
// with the matching is_correct flag.
InsertQuizAnswerOption(ctx context.Context, arg InsertQuizAnswerOptionParams) error
// Insert a single question row. reference_answer is only meaningful
// for `freeform` questions; the service passes NULL for the other
// two types. sort_order is required (the service sets a stable
// value -- either the user-supplied integer or the array index).
InsertQuizQuestion(ctx context.Context, arg InsertQuizQuestionParams) (pgtype.UUID, error)
// Study guide list queries (ASK-104).
//
// Every ListStudyGuides* variant uses the same CTE structure so the
// per-row aggregates (vote_score, is_recommended, quiz_count) are
// computed once and can be referenced from the outer WHERE clause
// (e.g. for the score-sorted cursor predicate). The CTE pattern also
// keeps the 8 named variants near-identical apart from ORDER BY + the
// cursor predicate, which makes future maintenance (e.g. adding a new
// sort field) a mechanical edit.
//
// Soft-delete invariants enforced everywhere:
// * sg.deleted_at IS NULL — excludes guides marked for deletion
// * u.deleted_at IS NULL — excludes guides authored by a
// soft-deleted user; matches the
// convention established by ASK-143's
// section roster (a soft-deleted user
// disappears from public surfaces)
// * quizzes.deleted_at IS NULL — quiz_count excludes deleted quizzes
//
// Privacy floor on the creator payload: only id + first_name + last_name
// are selected. No email, no clerk_id -- same rule as
// SectionMemberResponse in ASK-143.
// Insert a new guide and return all the columns the service needs to
// construct the StudyGuideDetail response without an extra round trip.
// The course preflight (in service.go) gates on AssertCourseExists so
// the FK violation is unreachable in normal flow; the FK still acts
// as a backstop if a course is hard-deleted between preflight + insert.
InsertStudyGuide(ctx context.Context, arg InsertStudyGuideParams) (InsertStudyGuideRow, error)
// Inserts the (study_guide_id, recommended_by) row and returns the
// created_at PLUS the recommender's privacy-floor identity
// (first_name + last_name) via a CTE join to users. One round trip
// builds the entire RecommendationResponse payload; without the
// CTE the service would need a second SELECT against users just to
// pull the recommender's name.
//
// The (study_guide_id, recommended_by) PK from the schema makes a
// duplicate insert raise unique_violation (Postgres SQLSTATE 23505),
// which the service catches and maps to apperrors.ErrConflict (409).
InsertStudyGuideRecommendation(ctx context.Context, arg InsertStudyGuideRecommendationParams) (InsertStudyGuideRecommendationRow, error)
// Adds the user to the section as a 'student'. ON CONFLICT DO NOTHING
// keeps duplicate joins atomic (no PK violation surfacing) and concurrency
// safe; the service layer treats an empty result as the 409 "Already a
// member of this section" case.
JoinSection(ctx context.Context, arg JoinSectionParams) (CourseMember, error)
// Hard-deletes the membership row. RETURNING lets the service detect a
// no-op delete (sql.ErrNoRows) and map it to the 404 "Not a member of
// this section" response.
LeaveSection(ctx context.Context, arg LeaveSectionParams) (pgtype.UUID, error)
// Returns sections with a live member_count via LEFT JOIN (so sections
// with zero members still appear). Ordered most-recent term first using
// start_date when present, falling back to section_code. NULLS LAST keeps
// sections without a known start_date at the bottom.
ListCourseSections(ctx context.Context, courseID pgtype.UUID) ([]ListCourseSectionsRow, error)
ListCoursesCreatedAtAsc(ctx context.Context, arg ListCoursesCreatedAtAscParams) ([]ListCoursesCreatedAtAscRow, error)
ListCoursesCreatedAtDesc(ctx context.Context, arg ListCoursesCreatedAtDescParams) ([]ListCoursesCreatedAtDescRow, error)
// All ListCourses* variants share the same WHERE template
// (school_id, department, q filters + sort-specific cursor) and only
// differ in ORDER BY direction and the cursor field shape. This mirrors
// the per-sort-variant pattern in files.sql -- sqlc cannot parameterize
// ORDER BY, so each direction gets its own named query.
//
// The default sort (by department) uses a composite (department, number, id)
// cursor because (department) alone is not unique; the other sort fields
// use a simpler (field, id) cursor since the field is paired with the
// primary key as a tiebreaker.
ListCoursesDepartmentAsc(ctx context.Context, arg ListCoursesDepartmentAscParams) ([]ListCoursesDepartmentAscRow, error)
ListCoursesDepartmentDesc(ctx context.Context, arg ListCoursesDepartmentDescParams) ([]ListCoursesDepartmentDescRow, error)
ListCoursesNumberAsc(ctx context.Context, arg ListCoursesNumberAscParams) ([]ListCoursesNumberAscRow, error)
ListCoursesNumberDesc(ctx context.Context, arg ListCoursesNumberDescParams) ([]ListCoursesNumberDescRow, error)
ListCoursesTitleAsc(ctx context.Context, arg ListCoursesTitleAscParams) ([]ListCoursesTitleAscRow, error)
ListCoursesTitleDesc(ctx context.Context, arg ListCoursesTitleDescParams) ([]ListCoursesTitleDescRow, error)
// Attached files for the guide detail payload. Privacy floor: no
// user_id, no s3_key, no checksum. The file list shows only what a
// viewer needs to see: what's attached, what type, and how big.
//
// Filters f.status = 'complete' so files mid-upload (pending) or
// failed don't surface in the guide detail -- a frontend that tried
// to download such a file would get a broken link. Only successfully
// uploaded files are visible to non-owners; the upload author's own
// file list (via the files endpoints) shows all statuses so they can
// retry or remove.
ListGuideFiles(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideFilesRow, error)
// Non-deleted quizzes for the guide + question_count per quiz. The
// LEFT JOIN ensures quizzes with zero questions still appear with
// question_count = 0.
ListGuideQuizzesWithQuestionCount(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideQuizzesWithQuestionCountRow, error)
// Recommenders list for the guide detail payload. Same privacy floor
// as CreatorSummary -- id + first_name + last_name only. Excludes
// recommenders whose user record is soft-deleted.
ListGuideRecommenders(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideRecommendersRow, error)
// Attached resources for the guide detail payload. No creator info
// in the SELECT list -- the caller doesn't need to know who attached
// the resource.
ListGuideResources(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideResourcesRow, error)
// Returns every section a user is enrolled in with the compact
// course + school payload the dashboard renders. Optional term + role
// filters use sqlc.narg so the WHERE branch short-circuits when
// they're absent. Sort is fixed: most-recent term first (lexicographic
// "Spring 2026" > "Fall 2025" is acceptable for MVP per the spec),
// then department + number for stable in-term ordering.
ListMyEnrollments(ctx context.Context, arg ListMyEnrollmentsParams) ([]ListMyEnrollmentsRow, error)
ListOwnedFilesCreatedAsc(ctx context.Context, arg ListOwnedFilesCreatedAscParams) ([]ListOwnedFilesCreatedAscRow, error)
ListOwnedFilesCreatedDesc(ctx context.Context, arg ListOwnedFilesCreatedDescParams) ([]ListOwnedFilesCreatedDescRow, error)
ListOwnedFilesMimeAsc(ctx context.Context, arg ListOwnedFilesMimeAscParams) ([]ListOwnedFilesMimeAscRow, error)
ListOwnedFilesMimeDesc(ctx context.Context, arg ListOwnedFilesMimeDescParams) ([]ListOwnedFilesMimeDescRow, error)
ListOwnedFilesNameAsc(ctx context.Context, arg ListOwnedFilesNameAscParams) ([]ListOwnedFilesNameAscRow, error)
ListOwnedFilesNameDesc(ctx context.Context, arg ListOwnedFilesNameDescParams) ([]ListOwnedFilesNameDescRow, error)
ListOwnedFilesSizeAsc(ctx context.Context, arg ListOwnedFilesSizeAscParams) ([]ListOwnedFilesSizeAscRow, error)
ListOwnedFilesSizeDesc(ctx context.Context, arg ListOwnedFilesSizeDescParams) ([]ListOwnedFilesSizeDescRow, error)
ListOwnedFilesStatusAsc(ctx context.Context, arg ListOwnedFilesStatusAscParams) ([]ListOwnedFilesStatusAscRow, error)
ListOwnedFilesStatusDesc(ctx context.Context, arg ListOwnedFilesStatusDescParams) ([]ListOwnedFilesStatusDescRow, error)
ListOwnedFilesUpdatedAsc(ctx context.Context, arg ListOwnedFilesUpdatedAscParams) ([]ListOwnedFilesUpdatedAscRow, error)
ListOwnedFilesUpdatedDesc(ctx context.Context, arg ListOwnedFilesUpdatedDescParams) ([]ListOwnedFilesUpdatedDescRow, error)
// All answer options for every question in a quiz, ordered by
// question_id then sort_order then id. The mapper groups by
// question_id in Go to attach options to their parent question.
// The triple-key ordering keeps the option list deterministic.
ListQuizAnswerOptionsByQuiz(ctx context.Context, quizID pgtype.UUID) ([]QuizAnswerOption, error)
// All questions for a quiz, ordered by sort_order then id (the id
// tiebreaker keeps the response deterministic when two questions
// happen to share a sort_order -- the spec doesn't enforce
// uniqueness on sort_order). Returns reference_answer so the
// mapper can emit it as `correct_answer` on freeform questions.
ListQuizQuestionsByQuiz(ctx context.Context, quizID pgtype.UUID) ([]ListQuizQuestionsByQuizRow, error)
// Lists every non-soft-deleted quiz attached to a study guide
// (ASK-136). Each row carries the privacy-floor creator payload
// (id + first_name + last_name only -- mirrors the studyguides
// surface) plus a server-computed question_count via LEFT JOIN +
// COUNT, so a quiz with zero questions still surfaces with a 0
// count rather than being silently dropped by an INNER JOIN.
//
// Soft-delete invariants:
// * q.deleted_at IS NULL -- excludes soft-deleted quizzes
// (AC3: studyguide with mixed live +
// deleted quizzes only returns the live
// ones)
// * u.deleted_at IS NULL -- excludes quizzes whose creator's user
// record was soft-deleted (matches the
// ASK-143 convention used by
// GetStudyGuideDetail)
//
// The parent study guide's deleted_at is checked separately by the
// service via GuideExistsAndLiveForQuizzes BEFORE this query runs --
// a missing or soft-deleted guide returns 404 even when this query
// would have returned an empty array. Keeps the 404 vs 200-empty
// distinction crisp.
//
// Order: created_at DESC with id DESC as the deterministic
// tiebreaker (the spec calls for "newest first"). The id tiebreaker
// prevents a flaky test on a Postgres that happens to insert two
// rows in the same microsecond.
ListQuizzesByStudyGuide(ctx context.Context, studyGuideID pgtype.UUID) ([]ListQuizzesByStudyGuideRow, error)
ListSchools(ctx context.Context, arg ListSchoolsParams) ([]School, error)
// Returns the section roster joined against users for first/last name.
// Privacy floor: SELECT lists ONLY the five fields exposed in the
// SectionMemberResponse schema (user_id, first_name, last_name, role,
// joined_at). DO NOT add email, clerk_id, or any other user column to
// this list -- the endpoint is reachable by any authenticated user.
//
// Soft-deleted users (users.deleted_at IS NOT NULL) are excluded -- the
// codebase's soft-delete convention is enforced by the partial indexes
// idx_users_deleted_at and idx_users_active_email. A user's soft-delete
// is the signal that they want to disappear from the product, so they
// must not surface in a public-by-design roster. The cursor still
// advances past them in the (joined_at, user_id) keyset, so removing
// them mid-iteration just shrinks the page rather than skipping live
// members.
//
// Optional role filter via sqlc.narg short-circuits when absent. Keyset
// pagination on (joined_at, user_id) -- joined_at alone isn't unique
// (multiple users can join in the same second on a busy section), so
// user_id is the tiebreaker that keeps the keyset a strict total order.
ListSectionMembers(ctx context.Context, arg ListSectionMembersParams) ([]ListSectionMembersRow, error)
ListStudyGuidesNewestAsc(ctx context.Context, arg ListStudyGuidesNewestAscParams) ([]ListStudyGuidesNewestAscRow, error)
ListStudyGuidesNewestDesc(ctx context.Context, arg ListStudyGuidesNewestDescParams) ([]ListStudyGuidesNewestDescRow, error)
ListStudyGuidesScoreAsc(ctx context.Context, arg ListStudyGuidesScoreAscParams) ([]ListStudyGuidesScoreAscRow, error)
// Default sort. Multi-column keyset on (vote_score, view_count,
// updated_at, id) -- each column after vote_score is a tiebreaker for
// the previous one; id is the final strict-total-order tiebreaker.
ListStudyGuidesScoreDesc(ctx context.Context, arg ListStudyGuidesScoreDescParams) ([]ListStudyGuidesScoreDescRow, error)
ListStudyGuidesUpdatedAsc(ctx context.Context, arg ListStudyGuidesUpdatedAscParams) ([]ListStudyGuidesUpdatedAscRow, error)
ListStudyGuidesUpdatedDesc(ctx context.Context, arg ListStudyGuidesUpdatedDescParams) ([]ListStudyGuidesUpdatedDescRow, error)
ListStudyGuidesViewsAsc(ctx context.Context, arg ListStudyGuidesViewsAscParams) ([]ListStudyGuidesViewsAscRow, error)
ListStudyGuidesViewsDesc(ctx context.Context, arg ListStudyGuidesViewsDescParams) ([]ListStudyGuidesViewsDescRow, error)
// Called by the cleanup job handler once S3 deletion is confirmed.
MarkFileDeleted(ctx context.Context, fileID pgtype.UUID) error
// Deletes a file grant matching the exact composite key. No-op if the grant
// does not exist (idempotent).
RevokeFileGrant(ctx context.Context, arg RevokeFileGrantParams) error
// Verifies the section exists AND belongs to the supplied course. A
// section UUID that targets a different course is treated as not found
// to avoid leaking the existence of unrelated sections via the URL path.
SectionInCourseExists(ctx context.Context, arg SectionInCourseExistsParams) (bool, error)
// Records the QStash message ID after publishing the async cleanup job.
SetFileDeletionJobID(ctx context.Context, arg SetFileDeletionJobIDParams) error
// Marks a file as pending deletion. Only applies if the file is owned by the caller
// and has not already entered a deletion state (idempotency-safe).
SoftDeleteFile(ctx context.Context, arg SoftDeleteFileParams) (int64, error)
// Set deleted_at = now() on the quiz. The service has already
// verified the row exists, isn't already deleted, and the viewer
// is the creator -- so this is a blind UPDATE. No cascade: practice
// sessions, questions, and answer options are preserved per the
// ASK-102 spec ("preserve historical practice data; the quiz
// simply becomes invisible to list/detail endpoints").
SoftDeleteQuiz(ctx context.Context, id pgtype.UUID) error
// Application-level cascade: soft-delete every non-deleted quiz on
// the guide. WHERE deleted_at IS NULL preserves the deleted_at
// timestamp on quizzes that were already soft-deleted before the
// guide was -- the spec explicitly requires that an already-deleted
// quiz's deleted_at is NOT updated by this cascade.
SoftDeleteQuizzesForGuide(ctx context.Context, studyGuideID pgtype.UUID) error
// Set deleted_at = now() on the guide. The service has already
// verified the row exists, isn't already deleted, and the viewer is
// the creator -- so this is a blind UPDATE. The DeleteStudyGuide
// transaction wraps this + SoftDeleteQuizzesForGuide.
SoftDeleteStudyGuide(ctx context.Context, id pgtype.UUID) error
SoftDeleteUserByClerkID(ctx context.Context, clerkID string) (int64, error)
// Pre-flight conflict check for AttachResource (ASK-111). Returns
// TRUE when ANY resource with this URL is already attached to the
// given guide -- regardless of who created the resource row. Lets
// the service short-circuit to 409 BEFORE the resource upsert, so a
// duplicate attempt doesn't create or touch a resources row only to
// discard it on the join PK violation.
//
// Why "regardless of creator": the join PK is (resource_id,
// study_guide_id), so two distinct resource rows (different creators
// but same URL) could both attach to the same guide without raising
// the join PK constraint. The spec treats that as a duplicate URL
// on the guide -- this query enforces the no-duplicate-URLs-per-guide
// contract at the application layer.
URLAlreadyAttachedToGuide(ctx context.Context, arg URLAlreadyAttachedToGuideParams) (bool, error)
// Renames a file. Only applies if owned by the caller and not in a deletion state.
// Returns sql.ErrNoRows when file is not found, not owned, or in deletion.
UpdateFile(ctx context.Context, arg UpdateFileParams) (UpdateFileRow, error)
UpdateFileStatus(ctx context.Context, arg UpdateFileStatusParams) error
// Partial update for ASK-153. The title column uses the standard
// COALESCE(narg, current) pattern -- nil means "leave alone".
//
// Description uses a CASE expression because COALESCE can't
// distinguish "field absent in the request" from "field
// explicitly null in the request" (both encode as SQL NULL once
// they reach the query layer). The handler resolves the
// tri-state, sets `clear_description` true on an explicit
// `description: null` body, and the service drives both args
// accordingly:
// * clear_description=false -> column unchanged
// * clear_description=true, description=NULL -> column cleared
// * clear_description=true, description="x" -> column set to "x"
//
// The service is responsible for 404 / 403 gating before this
// query runs (via GetQuizForUpdateWithParentStatus). updated_at
// is bumped to now() on every successful call -- the at-least-
// one-field rule is enforced in Go so this query is never
// reached for an empty PATCH.
UpdateQuiz(ctx context.Context, arg UpdateQuizParams) error
// Partial update for ASK-129. Each updatable column uses COALESCE(narg,
// current) so a nil arg from Go means "leave this column alone" and a
// non-nil arg means "replace with the supplied value". The service is
// responsible for:
// * 404 / 403 gating (via GetStudyGuideByIDForUpdate before this).
// * Validating the at-least-one-field rule (an empty body is a 400
// before this query runs).
// * Tag normalization (trim + lowercase + dedupe) -- the array
// written here is the final canonical form.
//
// The service runs the locked SELECT + this UPDATE in a single
// transaction so a concurrent delete can't slip in between. updated_at
// is bumped to now() on every successful call (the UPDATE sees at
// least the updated_at change even when every other narg is NULL,
// which matches the spec's "updated_at reflects the latest" guarantee
// but also means a no-op PATCH still bumps updated_at -- the service's
// empty-body 400 check prevents that case from reaching SQL).
UpdateStudyGuide(ctx context.Context, arg UpdateStudyGuideParams) error
UpsertClerkUser(ctx context.Context, arg UpsertClerkUserParams) (User, error)
// Inserts a new file grant, returning the row. If the grant already exists
// (same file_id, grantee_type, grantee_id, permission), updates granted_by
// and returns the row. Using DO UPDATE SET avoids a race window where
// concurrent inserts could cause both INSERT and fallback SELECT to miss.
UpsertFileGrant(ctx context.Context, arg UpsertFileGrantParams) (FileGrant, error)
// Inserts a new resources row for the (creator_id, url) pair. The
// ON CONFLICT DO NOTHING preserves the existing row's title /
// description / type when the viewer has used this URL before -- a
// silent overwrite would mutate state visible to the resource's
// other attachments (the same row may be attached to other guides
// + courses).
//
// Paired with GetResourceByCreatorURL: the service runs both calls
// in sequence, then uses the SELECT'd row regardless of whether the
// INSERT actually wrote.
UpsertResource(ctx context.Context, arg UpsertResourceParams) error
// Cast or change a vote (ASK-139). Inserts a new (user_id,
// study_guide_id, vote) row when the viewer has not voted, or
// updates the existing row's vote when the direction changes. Same-
// direction re-submits hit the WHERE clause on the DO UPDATE branch
// and become a true no-op (no row touched, no trigger fired,
// updated_at preserved). The (user_id, study_guide_id) PK from the
// schema is what makes ON CONFLICT resolve correctly.
UpsertStudyGuideVote(ctx context.Context, arg UpsertStudyGuideVoteParams) error
// Combined live-presence + role-gate probe for the recommend
// endpoints (ASK-147 + ASK-101). Returns one row when the viewer
// holds instructor or ta role in AT LEAST ONE section of the guide's
// course AND the guide is live (not soft-deleted).
//
// Returns three booleans so the service can distinguish 404 from
// 403 with a single round trip:
// * guide_exists -- guide row present AND deleted_at IS NULL
// * has_role -- viewer is instructor/ta in some section
// of the guide's course (ignored if guide
// doesn't exist)
//
// Combining the two checks into a single query (rather than two
// sequential calls) keeps the recommend hot path at one DB round
// trip for the gate; the actual insert/delete is the second.
//
// NULL-semantics note: when the guide doesn't exist, the inner
// `guide` CTE returns 0 rows, so `(SELECT course_id FROM guide)` is
// NULL, and `cs.course_id = NULL` is always FALSE (not NULL-equal).
// That makes `has_role` correctly false for missing guides without
// needing a separate WHERE EXISTS guard. The service short-circuits
// on !guide_exists before inspecting has_role, so the two booleans
// are independent by contract even though they correlate in this
// edge case.
ViewerCanRecommendForGuide(ctx context.Context, arg ViewerCanRecommendForGuideParams) (ViewerCanRecommendForGuideRow, error)
}
type Queries
type Queries struct {
// contains filtered or unexported fields
}
func New
func New(db DBTX) *Queries
func (*Queries) ComputeGuideVoteScore
func (q *Queries) ComputeGuideVoteScore(ctx context.Context, studyGuideID pgtype.UUID) (int64, error)
Recomputes the guide's vote_score from study_guide_votes. Returned as int64 to match the wire shape on CastVoteResponse. Run after the upsert in the same logical request so the response reflects the post-mutation state.
func (*Queries) CourseExists
func (q *Queries) CourseExists(ctx context.Context, id pgtype.UUID) (bool, error)
Single-row existence probe used by join/leave to disambiguate the "Course not found" 404 from the "Section not found" 404 the spec requires (see ASK-132 / ASK-138).
func (*Queries) CourseExistsForGuides
func (q *Queries) CourseExistsForGuides(ctx context.Context, id pgtype.UUID) (bool, error)
Single-row probe used by the list handler to disambiguate "course missing" (404) from "course exists but has no guides" (200 empty array). Separate from courses.CourseExists only because sqlc-generated queriers are per-file; the predicate is identical.
func (*Queries) DeleteGuideFile
func (q *Queries) DeleteGuideFile(ctx context.Context, arg DeleteGuideFileParams) (int64, error)
Removes the (file_id, study_guide_id) join row. Returns rows- affected so the service can detect the concurrency-race case (0 rows = a parallel detach already removed it, still maps to 404 to match the get-then-delete contract). The file row is preserved -- it may be attached to other guides + courses, and the spec explicitly forbids cascading the file delete from a single detach.
func (*Queries) DeleteGuideResource
func (q *Queries) DeleteGuideResource(ctx context.Context, arg DeleteGuideResourceParams) (int64, error)
Removes the join row only. The resources row is preserved -- it may be attached to other guides + courses, and the spec explicitly forbids cascading the resource delete from a single detach. Returns rows-affected so the service can detect already-detached races (0 rows -> 404) vs success (1 row -> nil).
func (*Queries) DeleteStudyGuideRecommendation
func (q *Queries) DeleteStudyGuideRecommendation(ctx context.Context, arg DeleteStudyGuideRecommendationParams) (int64, error)
Hard-delete the (viewer, guide) recommendation row. Returns the rows-affected count so the service can distinguish "viewer never recommended this guide" (0 rows -> 404 'Recommendation not found') from a successful delete (1 row -> 204). The guide-existence + role gate runs FIRST in the service so 'Study guide not found' / 403 win over 'Recommendation not found' when applicable.
func (*Queries) DeleteStudyGuideVote
func (q *Queries) DeleteStudyGuideVote(ctx context.Context, arg DeleteStudyGuideVoteParams) (int64, error)
Hard-delete the (viewer, guide) vote row (ASK-141). Returns the rows-affected count so the service can distinguish "no existing vote" (0 rows -> 404 'Vote not found') from a successful delete (1 row -> 204). The guide-existence check happens BEFORE this runs in the service so a missing guide doesn't leak through as "vote not found".
func (*Queries) GetCourse
func (q *Queries) GetCourse(ctx context.Context, id pgtype.UUID) (GetCourseRow, error)
func (*Queries) GetFileByOwner
func (q *Queries) GetFileByOwner(ctx context.Context, arg GetFileByOwnerParams) (GetFileByOwnerRow, error)
Fetches a file only if it belongs to the given user and has not been soft-deleted. Returns sql.ErrNoRows if not found or already in a deletion state.
func (*Queries) GetFileForAttach
func (q *Queries) GetFileForAttach(ctx context.Context, id pgtype.UUID) (GetFileForAttachRow, error)
File-side gate for AttachFile (ASK-121). Returns the file's ownership + status fields so the service can choose 403 (not owner) vs 404 (missing / not 'complete' / soft-deleted) without a second round trip. Filters NOTHING -- the service inspects status + deleted_at + deletion_status to decide vs returning pre-filtered for "is the row attachable" since the messages differ (403 vs 404) and we want to give the right one.
The columns mirror files.GetFileByOwner -- this is intentional; the cross-package read keeps the service layer aware of file ownership without reaching into the files package.
func (*Queries) GetFileIfViewable
func (q *Queries) GetFileIfViewable(ctx context.Context, arg GetFileIfViewableParams) (File, error)
func (*Queries) GetGuideResourceAttacher
func (q *Queries) GetGuideResourceAttacher(ctx context.Context, arg GetGuideResourceAttacherParams) (pgtype.UUID, error)
Lookup for DetachResource (ASK-116). Returns the attached_by user on the join row so the service can run the dual-authz check (viewer is guide creator OR viewer is attached_by). sql.ErrNoRows maps to 'Resource attachment not found' 404 -- the resource may exist but isn't attached to THIS guide.
func (*Queries) GetMembership
func (q *Queries) GetMembership(ctx context.Context, arg GetMembershipParams) (GetMembershipRow, error)
Single-row membership lookup powering the per-section enrolled/not-enrolled probe (ASK-148). Returns sql.ErrNoRows when the viewer is not a member; the service translates that into the 200 {enrolled:false} response, NOT a 404.
func (*Queries) GetQuizByIDForUpdate
func (q *Queries) GetQuizByIDForUpdate(ctx context.Context, id pgtype.UUID) (GetQuizByIDForUpdateRow, error)
Locked SELECT used at the start of DeleteQuiz (ASK-102) and UpdateQuiz (ASK-153). SELECT FOR UPDATE prevents two concurrent mutators from racing on the same row -- one wins with 204/200, the other sees the post-mutation state in its tx snapshot and returns 404. Filters NOTHING -- the service inspects deleted_at + creator_id to choose 404 vs 403 vs proceed (mirrors studyguides.GetStudyGuideByIDForUpdate).
func (*Queries) GetQuizDetail
func (q *Queries) GetQuizDetail(ctx context.Context, id pgtype.UUID) (GetQuizDetailRow, error)
Load the quiz row + privacy-floor creator info for the detail payload. The study guide is NOT joined back -- the caller already knows the study_guide_id (it's in the URL on POST and on the quiz row itself). Excludes soft-deleted quizzes (deleted_at IS NULL), soft-deleted creators (u.deleted_at IS NULL), and soft-deleted parent guides (sg.deleted_at IS NULL) so a hydration that races with a parent-cascade soft-delete reports 'not found' rather than rendering an orphaned quiz.
func (*Queries) GetQuizForUpdateWithParentStatus
func (q *Queries) GetQuizForUpdateWithParentStatus(ctx context.Context, id pgtype.UUID) (GetQuizForUpdateWithParentStatusRow, error)
Locked SELECT used by UpdateQuiz (ASK-153). Like GetQuizByIDForUpdate but also joins to the parent study guide so the service can enforce the "parent guide must be live" gate (AC6) inside the same transaction without a second round trip. Locks ONLY the quiz row (FOR UPDATE OF q) -- the parent guide is read-only at this site and we don't want to hold a write lock on it for the duration of the quiz update.
Filters NOTHING -- the service inspects the four fields to choose 404 (missing quiz / deleted quiz / deleted guide) vs 403 (not creator) vs proceed.
func (*Queries) GetResourceByCreatorURL
func (q *Queries) GetResourceByCreatorURL(ctx context.Context, arg GetResourceByCreatorURLParams) (GetResourceByCreatorURLRow, error)
Lookup pair for UpsertResource above. Returns the resources row the viewer owns for this URL; always succeeds because the upsert runs immediately before this in the same tx (either the INSERT wrote the row or it was already there).
func (*Queries) GetSchool
func (q *Queries) GetSchool(ctx context.Context, id pgtype.UUID) (School, error)
func (*Queries) GetStudyGuideByIDForUpdate
func (q *Queries) GetStudyGuideByIDForUpdate(ctx context.Context, id pgtype.UUID) (GetStudyGuideByIDForUpdateRow, error)
Locked SELECT used at the start of DeleteStudyGuide. SELECT FOR UPDATE prevents concurrent deletes from racing on the same guide (one wins with 204, the other sees the row already-deleted in its transaction's snapshot and returns 404). Filters NOTHING -- the service inspects deleted_at + creator_id to choose 404 vs 403 vs proceed.
func (*Queries) GetStudyGuideDetail
func (q *Queries) GetStudyGuideDetail(ctx context.Context, id pgtype.UUID) (GetStudyGuideDetailRow, error)
The detail endpoint's main query (ASK-114). Returns the guide's own columns + a compact course payload + a compact creator payload + two inline aggregates as subqueries:
- vote_score -- SUM(up/down votes)
- is_recommended -- EXISTS in study_guide_recommendations
The viewer's own vote (user_vote) ships in a separate query (GetUserVoteForGuide) because sqlc does not infer nullable output columns from LEFT JOIN / subquery expressions on enum-typed columns -- it reads the schema's NOT NULL constraint and types the output non-nullable. An extra round trip is cheaper than fighting sqlc's type inference; the PRD's "batching as separate queries" guidance explicitly allows it.
Soft-delete invariants:
- sg.deleted_at IS NULL -- excludes deleted guides (→ 404)
- u.deleted_at IS NULL -- creator must be live (ASK-143 convention)
Privacy floor: no email, no clerk_id. Creator exposes only id/first_name/last_name.
func (*Queries) GetUserIDByClerkID
func (q *Queries) GetUserIDByClerkID(ctx context.Context, clerkID string) (pgtype.UUID, error)
func (*Queries) GetUserVoteForGuide
func (q *Queries) GetUserVoteForGuide(ctx context.Context, arg GetUserVoteForGuideParams) (VoteDirection, error)
Returns the viewer's own vote on the guide, or sql.ErrNoRows when the viewer has not voted. The service maps ErrNoRows to a nil user_vote in the response (JSON null, not omitted).
func (*Queries) GuideExistsAndLive
func (q *Queries) GuideExistsAndLive(ctx context.Context, id pgtype.UUID) (bool, error)
Live-presence probe used by both vote endpoints. Returns TRUE only when the guide row exists AND is not soft-deleted. The vote service gates on this before the upsert/delete so a missing-or-deleted guide returns 404 with a clear message rather than e.g. trampling through to the SQL layer and surfacing a generic FK error.
func (*Queries) GuideExistsAndLiveForQuizzes
func (q *Queries) GuideExistsAndLiveForQuizzes(ctx context.Context, id pgtype.UUID) (bool, error)
Quizzes write + read queries (ASK-150 / ASK-136).
The create flow is wrapped in a single InTx in the service layer: InsertQuiz -> N x InsertQuizQuestion -> M x InsertQuizAnswerOption. A failure at any step rolls everything back, so a partial quiz can never be observed by another reader.
The post-insert hydration runs OUTSIDE the transaction (commit happens first) using GetQuizDetail + ListQuizQuestionsByQuiz + ListQuizAnswerOptionsByQuiz. The two-list fan-out matches the studyguides detail pattern -- mapping options back onto questions happens in Go because pgx returns flat rowsets and the question count is small (<=100 per quiz).
Privacy floor on the creator payload mirrors studyguides: id + first_name + last_name only. No email, no clerk_id. Live-presence probe for the create-quiz endpoint. Returns TRUE only when the guide row exists AND is not soft-deleted. The studyguides package has an identical query (GuideExistsAndLive); duplicated here so the quizzes service can stay decoupled from the studyguides Repository interface (sqlc generates queriers per package -- both call the same row but live in different generated method tables).
func (*Queries) GuideFileAttached
func (q *Queries) GuideFileAttached(ctx context.Context, arg GuideFileAttachedParams) (bool, error)
Lookup for DetachFile (ASK-124). Returns TRUE when the (file, guide) join row exists. Used as the 404 short-circuit before the delete fires -- we want a clean 'File attachment not found' rather than relying on DeleteGuideFile :execrows which can't distinguish 'never existed' from 'concurrent detach happened first'.
func (*Queries) InsertFile
func (q *Queries) InsertFile(ctx context.Context, arg InsertFileParams) (File, error)
func (*Queries) InsertGuideFile
func (q *Queries) InsertGuideFile(ctx context.Context, arg InsertGuideFileParams) (pgtype.Timestamptz, error)
Creates the (file_id, study_guide_id) join row. Uses ON CONFLICT DO NOTHING + RETURNING so a duplicate attach surfaces as sql.ErrNoRows in Go, which the service maps to a 409 'File is already attached to this study guide'. Same pattern as recommendations + JoinSection.
No attached_by column on this join table (unlike study_guide_resources) -- file ownership is determined from files.user_id instead, and the dual-authz check on detach compares against guide.creator_id + file.user_id.
func (*Queries) InsertGuideResource
func (q *Queries) InsertGuideResource(ctx context.Context, arg InsertGuideResourceParams) error
Creates the (resource_id, study_guide_id, attached_by) join row. The PK is (resource_id, study_guide_id) so a same-resource-and-guide duplicate raises a unique_violation -- but the user-facing 409 conflict on a duplicate URL is detected EARLIER by URLAlreadyAttachedToGuide (which catches across resource rows with the same URL but different creators). This INSERT's PK failure mode is the narrow concurrency-race: two attachers slip through the pre-check between query 1 and query 4.
func (*Queries) InsertQuiz
func (q *Queries) InsertQuiz(ctx context.Context, arg InsertQuizParams) (InsertQuizRow, error)
Insert a new quiz row. Returns the columns the service needs to build the QuizDetailResponse without an extra round trip on the write side -- the read-side hydration still happens via GetQuizDetail because the creator's first_name + last_name come from a join to users (and would inflate this RETURNING clause).
func (*Queries) InsertQuizAnswerOption
func (q *Queries) InsertQuizAnswerOption(ctx context.Context, arg InsertQuizAnswerOptionParams) error
Insert one option row. The service has already validated that exactly one option per MCQ has is_correct=true; for true-false questions the service synthesises two options (`True` + `False`) with the matching is_correct flag.
func (*Queries) InsertQuizQuestion
func (q *Queries) InsertQuizQuestion(ctx context.Context, arg InsertQuizQuestionParams) (pgtype.UUID, error)
Insert a single question row. reference_answer is only meaningful for `freeform` questions; the service passes NULL for the other two types. sort_order is required (the service sets a stable value -- either the user-supplied integer or the array index).
func (*Queries) InsertStudyGuide
func (q *Queries) InsertStudyGuide(ctx context.Context, arg InsertStudyGuideParams) (InsertStudyGuideRow, error)
Study guide list queries (ASK-104).
Every ListStudyGuides* variant uses the same CTE structure so the per-row aggregates (vote_score, is_recommended, quiz_count) are computed once and can be referenced from the outer WHERE clause (e.g. for the score-sorted cursor predicate). The CTE pattern also keeps the 8 named variants near-identical apart from ORDER BY + the cursor predicate, which makes future maintenance (e.g. adding a new sort field) a mechanical edit.
Soft-delete invariants enforced everywhere:
- sg.deleted_at IS NULL — excludes guides marked for deletion
- u.deleted_at IS NULL — excludes guides authored by a soft-deleted user; matches the convention established by ASK-143's section roster (a soft-deleted user disappears from public surfaces)
- quizzes.deleted_at IS NULL — quiz_count excludes deleted quizzes
Privacy floor on the creator payload: only id + first_name + last_name are selected. No email, no clerk_id -- same rule as SectionMemberResponse in ASK-143. Insert a new guide and return all the columns the service needs to construct the StudyGuideDetail response without an extra round trip. The course preflight (in service.go) gates on AssertCourseExists so the FK violation is unreachable in normal flow; the FK still acts as a backstop if a course is hard-deleted between preflight + insert.
func (*Queries) InsertStudyGuideRecommendation
func (q *Queries) InsertStudyGuideRecommendation(ctx context.Context, arg InsertStudyGuideRecommendationParams) (InsertStudyGuideRecommendationRow, error)
Inserts the (study_guide_id, recommended_by) row and returns the created_at PLUS the recommender's privacy-floor identity (first_name + last_name) via a CTE join to users. One round trip builds the entire RecommendationResponse payload; without the CTE the service would need a second SELECT against users just to pull the recommender's name.
The (study_guide_id, recommended_by) PK from the schema makes a duplicate insert raise unique_violation (Postgres SQLSTATE 23505), which the service catches and maps to apperrors.ErrConflict (409).
func (*Queries) JoinSection
func (q *Queries) JoinSection(ctx context.Context, arg JoinSectionParams) (CourseMember, error)
Adds the user to the section as a 'student'. ON CONFLICT DO NOTHING keeps duplicate joins atomic (no PK violation surfacing) and concurrency safe; the service layer treats an empty result as the 409 "Already a member of this section" case.
func (*Queries) LeaveSection
func (q *Queries) LeaveSection(ctx context.Context, arg LeaveSectionParams) (pgtype.UUID, error)
Hard-deletes the membership row. RETURNING lets the service detect a no-op delete (sql.ErrNoRows) and map it to the 404 "Not a member of this section" response.
func (*Queries) ListCourseSections
func (q *Queries) ListCourseSections(ctx context.Context, courseID pgtype.UUID) ([]ListCourseSectionsRow, error)
Returns sections with a live member_count via LEFT JOIN (so sections with zero members still appear). Ordered most-recent term first using start_date when present, falling back to section_code. NULLS LAST keeps sections without a known start_date at the bottom.
func (*Queries) ListCoursesCreatedAtAsc
func (q *Queries) ListCoursesCreatedAtAsc(ctx context.Context, arg ListCoursesCreatedAtAscParams) ([]ListCoursesCreatedAtAscRow, error)
func (*Queries) ListCoursesCreatedAtDesc
func (q *Queries) ListCoursesCreatedAtDesc(ctx context.Context, arg ListCoursesCreatedAtDescParams) ([]ListCoursesCreatedAtDescRow, error)
func (*Queries) ListCoursesDepartmentAsc
func (q *Queries) ListCoursesDepartmentAsc(ctx context.Context, arg ListCoursesDepartmentAscParams) ([]ListCoursesDepartmentAscRow, error)
All ListCourses* variants share the same WHERE template (school_id, department, q filters + sort-specific cursor) and only differ in ORDER BY direction and the cursor field shape. This mirrors the per-sort-variant pattern in files.sql -- sqlc cannot parameterize ORDER BY, so each direction gets its own named query.
The default sort (by department) uses a composite (department, number, id) cursor because (department) alone is not unique; the other sort fields use a simpler (field, id) cursor since the field is paired with the primary key as a tiebreaker.
func (*Queries) ListCoursesDepartmentDesc
func (q *Queries) ListCoursesDepartmentDesc(ctx context.Context, arg ListCoursesDepartmentDescParams) ([]ListCoursesDepartmentDescRow, error)
func (*Queries) ListCoursesNumberAsc
func (q *Queries) ListCoursesNumberAsc(ctx context.Context, arg ListCoursesNumberAscParams) ([]ListCoursesNumberAscRow, error)
func (*Queries) ListCoursesNumberDesc
func (q *Queries) ListCoursesNumberDesc(ctx context.Context, arg ListCoursesNumberDescParams) ([]ListCoursesNumberDescRow, error)
func (*Queries) ListCoursesTitleAsc
func (q *Queries) ListCoursesTitleAsc(ctx context.Context, arg ListCoursesTitleAscParams) ([]ListCoursesTitleAscRow, error)
func (*Queries) ListCoursesTitleDesc
func (q *Queries) ListCoursesTitleDesc(ctx context.Context, arg ListCoursesTitleDescParams) ([]ListCoursesTitleDescRow, error)
func (*Queries) ListGuideFiles
func (q *Queries) ListGuideFiles(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideFilesRow, error)
Attached files for the guide detail payload. Privacy floor: no user_id, no s3_key, no checksum. The file list shows only what a viewer needs to see: what's attached, what type, and how big.
Filters f.status = 'complete' so files mid-upload (pending) or failed don't surface in the guide detail -- a frontend that tried to download such a file would get a broken link. Only successfully uploaded files are visible to non-owners; the upload author's own file list (via the files endpoints) shows all statuses so they can retry or remove.
func (*Queries) ListGuideQuizzesWithQuestionCount
func (q *Queries) ListGuideQuizzesWithQuestionCount(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideQuizzesWithQuestionCountRow, error)
Non-deleted quizzes for the guide + question_count per quiz. The LEFT JOIN ensures quizzes with zero questions still appear with question_count = 0.
func (*Queries) ListGuideRecommenders
func (q *Queries) ListGuideRecommenders(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideRecommendersRow, error)
Recommenders list for the guide detail payload. Same privacy floor as CreatorSummary -- id + first_name + last_name only. Excludes recommenders whose user record is soft-deleted.
func (*Queries) ListGuideResources
func (q *Queries) ListGuideResources(ctx context.Context, studyGuideID pgtype.UUID) ([]ListGuideResourcesRow, error)
Attached resources for the guide detail payload. No creator info in the SELECT list -- the caller doesn't need to know who attached the resource.
func (*Queries) ListMyEnrollments
func (q *Queries) ListMyEnrollments(ctx context.Context, arg ListMyEnrollmentsParams) ([]ListMyEnrollmentsRow, error)
Returns every section a user is enrolled in with the compact course + school payload the dashboard renders. Optional term + role filters use sqlc.narg so the WHERE branch short-circuits when they're absent. Sort is fixed: most-recent term first (lexicographic "Spring 2026" > "Fall 2025" is acceptable for MVP per the spec), then department + number for stable in-term ordering.
func (*Queries) ListOwnedFilesCreatedAsc
func (q *Queries) ListOwnedFilesCreatedAsc(ctx context.Context, arg ListOwnedFilesCreatedAscParams) ([]ListOwnedFilesCreatedAscRow, error)
func (*Queries) ListOwnedFilesCreatedDesc
func (q *Queries) ListOwnedFilesCreatedDesc(ctx context.Context, arg ListOwnedFilesCreatedDescParams) ([]ListOwnedFilesCreatedDescRow, error)
func (*Queries) ListOwnedFilesMimeAsc
func (q *Queries) ListOwnedFilesMimeAsc(ctx context.Context, arg ListOwnedFilesMimeAscParams) ([]ListOwnedFilesMimeAscRow, error)
func (*Queries) ListOwnedFilesMimeDesc
func (q *Queries) ListOwnedFilesMimeDesc(ctx context.Context, arg ListOwnedFilesMimeDescParams) ([]ListOwnedFilesMimeDescRow, error)
func (*Queries) ListOwnedFilesNameAsc
func (q *Queries) ListOwnedFilesNameAsc(ctx context.Context, arg ListOwnedFilesNameAscParams) ([]ListOwnedFilesNameAscRow, error)
func (*Queries) ListOwnedFilesNameDesc
func (q *Queries) ListOwnedFilesNameDesc(ctx context.Context, arg ListOwnedFilesNameDescParams) ([]ListOwnedFilesNameDescRow, error)
func (*Queries) ListOwnedFilesSizeAsc
func (q *Queries) ListOwnedFilesSizeAsc(ctx context.Context, arg ListOwnedFilesSizeAscParams) ([]ListOwnedFilesSizeAscRow, error)
func (*Queries) ListOwnedFilesSizeDesc
func (q *Queries) ListOwnedFilesSizeDesc(ctx context.Context, arg ListOwnedFilesSizeDescParams) ([]ListOwnedFilesSizeDescRow, error)
func (*Queries) ListOwnedFilesStatusAsc
func (q *Queries) ListOwnedFilesStatusAsc(ctx context.Context, arg ListOwnedFilesStatusAscParams) ([]ListOwnedFilesStatusAscRow, error)
func (*Queries) ListOwnedFilesStatusDesc
func (q *Queries) ListOwnedFilesStatusDesc(ctx context.Context, arg ListOwnedFilesStatusDescParams) ([]ListOwnedFilesStatusDescRow, error)
func (*Queries) ListOwnedFilesUpdatedAsc
func (q *Queries) ListOwnedFilesUpdatedAsc(ctx context.Context, arg ListOwnedFilesUpdatedAscParams) ([]ListOwnedFilesUpdatedAscRow, error)
func (*Queries) ListOwnedFilesUpdatedDesc
func (q *Queries) ListOwnedFilesUpdatedDesc(ctx context.Context, arg ListOwnedFilesUpdatedDescParams) ([]ListOwnedFilesUpdatedDescRow, error)
func (*Queries) ListQuizAnswerOptionsByQuiz
func (q *Queries) ListQuizAnswerOptionsByQuiz(ctx context.Context, quizID pgtype.UUID) ([]QuizAnswerOption, error)
All answer options for every question in a quiz, ordered by question_id then sort_order then id. The mapper groups by question_id in Go to attach options to their parent question. The triple-key ordering keeps the option list deterministic.
func (*Queries) ListQuizQuestionsByQuiz
func (q *Queries) ListQuizQuestionsByQuiz(ctx context.Context, quizID pgtype.UUID) ([]ListQuizQuestionsByQuizRow, error)
All questions for a quiz, ordered by sort_order then id (the id tiebreaker keeps the response deterministic when two questions happen to share a sort_order -- the spec doesn't enforce uniqueness on sort_order). Returns reference_answer so the mapper can emit it as `correct_answer` on freeform questions.
func (*Queries) ListQuizzesByStudyGuide
func (q *Queries) ListQuizzesByStudyGuide(ctx context.Context, studyGuideID pgtype.UUID) ([]ListQuizzesByStudyGuideRow, error)
Lists every non-soft-deleted quiz attached to a study guide (ASK-136). Each row carries the privacy-floor creator payload (id + first_name + last_name only -- mirrors the studyguides surface) plus a server-computed question_count via LEFT JOIN + COUNT, so a quiz with zero questions still surfaces with a 0 count rather than being silently dropped by an INNER JOIN.
Soft-delete invariants:
- q.deleted_at IS NULL -- excludes soft-deleted quizzes (AC3: studyguide with mixed live + deleted quizzes only returns the live ones)
- u.deleted_at IS NULL -- excludes quizzes whose creator's user record was soft-deleted (matches the ASK-143 convention used by GetStudyGuideDetail)
The parent study guide's deleted_at is checked separately by the service via GuideExistsAndLiveForQuizzes BEFORE this query runs -- a missing or soft-deleted guide returns 404 even when this query would have returned an empty array. Keeps the 404 vs 200-empty distinction crisp.
Order: created_at DESC with id DESC as the deterministic tiebreaker (the spec calls for "newest first"). The id tiebreaker prevents a flaky test on a Postgres that happens to insert two rows in the same microsecond.
func (*Queries) ListSchools
func (q *Queries) ListSchools(ctx context.Context, arg ListSchoolsParams) ([]School, error)
func (*Queries) ListSectionMembers
func (q *Queries) ListSectionMembers(ctx context.Context, arg ListSectionMembersParams) ([]ListSectionMembersRow, error)
Returns the section roster joined against users for first/last name. Privacy floor: SELECT lists ONLY the five fields exposed in the SectionMemberResponse schema (user_id, first_name, last_name, role, joined_at). DO NOT add email, clerk_id, or any other user column to this list -- the endpoint is reachable by any authenticated user.
Soft-deleted users (users.deleted_at IS NOT NULL) are excluded -- the codebase's soft-delete convention is enforced by the partial indexes idx_users_deleted_at and idx_users_active_email. A user's soft-delete is the signal that they want to disappear from the product, so they must not surface in a public-by-design roster. The cursor still advances past them in the (joined_at, user_id) keyset, so removing them mid-iteration just shrinks the page rather than skipping live members.
Optional role filter via sqlc.narg short-circuits when absent. Keyset pagination on (joined_at, user_id) -- joined_at alone isn't unique (multiple users can join in the same second on a busy section), so user_id is the tiebreaker that keeps the keyset a strict total order.
func (*Queries) ListStudyGuidesNewestAsc
func (q *Queries) ListStudyGuidesNewestAsc(ctx context.Context, arg ListStudyGuidesNewestAscParams) ([]ListStudyGuidesNewestAscRow, error)
func (*Queries) ListStudyGuidesNewestDesc
func (q *Queries) ListStudyGuidesNewestDesc(ctx context.Context, arg ListStudyGuidesNewestDescParams) ([]ListStudyGuidesNewestDescRow, error)
func (*Queries) ListStudyGuidesScoreAsc
func (q *Queries) ListStudyGuidesScoreAsc(ctx context.Context, arg ListStudyGuidesScoreAscParams) ([]ListStudyGuidesScoreAscRow, error)
func (*Queries) ListStudyGuidesScoreDesc
func (q *Queries) ListStudyGuidesScoreDesc(ctx context.Context, arg ListStudyGuidesScoreDescParams) ([]ListStudyGuidesScoreDescRow, error)
Default sort. Multi-column keyset on (vote_score, view_count, updated_at, id) -- each column after vote_score is a tiebreaker for the previous one; id is the final strict-total-order tiebreaker.
func (*Queries) ListStudyGuidesUpdatedAsc
func (q *Queries) ListStudyGuidesUpdatedAsc(ctx context.Context, arg ListStudyGuidesUpdatedAscParams) ([]ListStudyGuidesUpdatedAscRow, error)
func (*Queries) ListStudyGuidesUpdatedDesc
func (q *Queries) ListStudyGuidesUpdatedDesc(ctx context.Context, arg ListStudyGuidesUpdatedDescParams) ([]ListStudyGuidesUpdatedDescRow, error)
func (*Queries) ListStudyGuidesViewsAsc
func (q *Queries) ListStudyGuidesViewsAsc(ctx context.Context, arg ListStudyGuidesViewsAscParams) ([]ListStudyGuidesViewsAscRow, error)
func (*Queries) ListStudyGuidesViewsDesc
func (q *Queries) ListStudyGuidesViewsDesc(ctx context.Context, arg ListStudyGuidesViewsDescParams) ([]ListStudyGuidesViewsDescRow, error)
func (*Queries) MarkFileDeleted
func (q *Queries) MarkFileDeleted(ctx context.Context, fileID pgtype.UUID) error
Called by the cleanup job handler once S3 deletion is confirmed.
func (*Queries) RevokeFileGrant
func (q *Queries) RevokeFileGrant(ctx context.Context, arg RevokeFileGrantParams) error
Deletes a file grant matching the exact composite key. No-op if the grant does not exist (idempotent).
func (*Queries) SectionInCourseExists
func (q *Queries) SectionInCourseExists(ctx context.Context, arg SectionInCourseExistsParams) (bool, error)
Verifies the section exists AND belongs to the supplied course. A section UUID that targets a different course is treated as not found to avoid leaking the existence of unrelated sections via the URL path.
func (*Queries) SetFileDeletionJobID
func (q *Queries) SetFileDeletionJobID(ctx context.Context, arg SetFileDeletionJobIDParams) error
Records the QStash message ID after publishing the async cleanup job.
func (*Queries) SoftDeleteFile
func (q *Queries) SoftDeleteFile(ctx context.Context, arg SoftDeleteFileParams) (int64, error)
Marks a file as pending deletion. Only applies if the file is owned by the caller and has not already entered a deletion state (idempotency-safe).
func (*Queries) SoftDeleteQuiz
func (q *Queries) SoftDeleteQuiz(ctx context.Context, id pgtype.UUID) error
Set deleted_at = now() on the quiz. The service has already verified the row exists, isn't already deleted, and the viewer is the creator -- so this is a blind UPDATE. No cascade: practice sessions, questions, and answer options are preserved per the ASK-102 spec ("preserve historical practice data; the quiz simply becomes invisible to list/detail endpoints").
func (*Queries) SoftDeleteQuizzesForGuide
func (q *Queries) SoftDeleteQuizzesForGuide(ctx context.Context, studyGuideID pgtype.UUID) error
Application-level cascade: soft-delete every non-deleted quiz on the guide. WHERE deleted_at IS NULL preserves the deleted_at timestamp on quizzes that were already soft-deleted before the guide was -- the spec explicitly requires that an already-deleted quiz's deleted_at is NOT updated by this cascade.
func (*Queries) SoftDeleteStudyGuide
func (q *Queries) SoftDeleteStudyGuide(ctx context.Context, id pgtype.UUID) error
Set deleted_at = now() on the guide. The service has already verified the row exists, isn't already deleted, and the viewer is the creator -- so this is a blind UPDATE. The DeleteStudyGuide transaction wraps this + SoftDeleteQuizzesForGuide.
func (*Queries) SoftDeleteUserByClerkID
func (q *Queries) SoftDeleteUserByClerkID(ctx context.Context, clerkID string) (int64, error)
func (*Queries) URLAlreadyAttachedToGuide
func (q *Queries) URLAlreadyAttachedToGuide(ctx context.Context, arg URLAlreadyAttachedToGuideParams) (bool, error)
Pre-flight conflict check for AttachResource (ASK-111). Returns TRUE when ANY resource with this URL is already attached to the given guide -- regardless of who created the resource row. Lets the service short-circuit to 409 BEFORE the resource upsert, so a duplicate attempt doesn't create or touch a resources row only to discard it on the join PK violation.
Why "regardless of creator": the join PK is (resource_id, study_guide_id), so two distinct resource rows (different creators but same URL) could both attach to the same guide without raising the join PK constraint. The spec treats that as a duplicate URL on the guide -- this query enforces the no-duplicate-URLs-per-guide contract at the application layer.
func (*Queries) UpdateFile
func (q *Queries) UpdateFile(ctx context.Context, arg UpdateFileParams) (UpdateFileRow, error)
Renames a file. Only applies if owned by the caller and not in a deletion state. Returns sql.ErrNoRows when file is not found, not owned, or in deletion.
func (*Queries) UpdateFileStatus
func (q *Queries) UpdateFileStatus(ctx context.Context, arg UpdateFileStatusParams) error
func (*Queries) UpdateQuiz
func (q *Queries) UpdateQuiz(ctx context.Context, arg UpdateQuizParams) error
Partial update for ASK-153. The title column uses the standard COALESCE(narg, current) pattern -- nil means "leave alone".
Description uses a CASE expression because COALESCE can't distinguish "field absent in the request" from "field explicitly null in the request" (both encode as SQL NULL once they reach the query layer). The handler resolves the tri-state, sets `clear_description` true on an explicit `description: null` body, and the service drives both args accordingly:
- clear_description=false -> column unchanged
- clear_description=true, description=NULL -> column cleared
- clear_description=true, description="x" -> column set to "x"
The service is responsible for 404 / 403 gating before this query runs (via GetQuizForUpdateWithParentStatus). updated_at is bumped to now() on every successful call -- the at-least- one-field rule is enforced in Go so this query is never reached for an empty PATCH.
func (*Queries) UpdateStudyGuide
func (q *Queries) UpdateStudyGuide(ctx context.Context, arg UpdateStudyGuideParams) error
Partial update for ASK-129. Each updatable column uses COALESCE(narg, current) so a nil arg from Go means "leave this column alone" and a non-nil arg means "replace with the supplied value". The service is responsible for:
- 404 / 403 gating (via GetStudyGuideByIDForUpdate before this).
- Validating the at-least-one-field rule (an empty body is a 400 before this query runs).
- Tag normalization (trim + lowercase + dedupe) -- the array written here is the final canonical form.
The service runs the locked SELECT + this UPDATE in a single transaction so a concurrent delete can't slip in between. updated_at is bumped to now() on every successful call (the UPDATE sees at least the updated_at change even when every other narg is NULL, which matches the spec's "updated_at reflects the latest" guarantee but also means a no-op PATCH still bumps updated_at -- the service's empty-body 400 check prevents that case from reaching SQL).
func (*Queries) UpsertClerkUser
func (q *Queries) UpsertClerkUser(ctx context.Context, arg UpsertClerkUserParams) (User, error)
func (*Queries) UpsertFileGrant
func (q *Queries) UpsertFileGrant(ctx context.Context, arg UpsertFileGrantParams) (FileGrant, error)
Inserts a new file grant, returning the row. If the grant already exists (same file_id, grantee_type, grantee_id, permission), updates granted_by and returns the row. Using DO UPDATE SET avoids a race window where concurrent inserts could cause both INSERT and fallback SELECT to miss.
func (*Queries) UpsertResource
func (q *Queries) UpsertResource(ctx context.Context, arg UpsertResourceParams) error
Inserts a new resources row for the (creator_id, url) pair. The ON CONFLICT DO NOTHING preserves the existing row's title / description / type when the viewer has used this URL before -- a silent overwrite would mutate state visible to the resource's other attachments (the same row may be attached to other guides + courses).
Paired with GetResourceByCreatorURL: the service runs both calls in sequence, then uses the SELECT'd row regardless of whether the INSERT actually wrote.
func (*Queries) UpsertStudyGuideVote
func (q *Queries) UpsertStudyGuideVote(ctx context.Context, arg UpsertStudyGuideVoteParams) error
Cast or change a vote (ASK-139). Inserts a new (user_id, study_guide_id, vote) row when the viewer has not voted, or updates the existing row's vote when the direction changes. Same- direction re-submits hit the WHERE clause on the DO UPDATE branch and become a true no-op (no row touched, no trigger fired, updated_at preserved). The (user_id, study_guide_id) PK from the schema is what makes ON CONFLICT resolve correctly.
func (*Queries) ViewerCanRecommendForGuide
func (q *Queries) ViewerCanRecommendForGuide(ctx context.Context, arg ViewerCanRecommendForGuideParams) (ViewerCanRecommendForGuideRow, error)
Combined live-presence + role-gate probe for the recommend endpoints (ASK-147 + ASK-101). Returns one row when the viewer holds instructor or ta role in AT LEAST ONE section of the guide's course AND the guide is live (not soft-deleted).
Returns three booleans so the service can distinguish 404 from 403 with a single round trip:
- guide_exists -- guide row present AND deleted_at IS NULL
- has_role -- viewer is instructor/ta in some section of the guide's course (ignored if guide doesn't exist)
Combining the two checks into a single query (rather than two sequential calls) keeps the recommend hot path at one DB round trip for the gate; the actual insert/delete is the second.
NULL-semantics note: when the guide doesn't exist, the inner `guide` CTE returns 0 rows, so `(SELECT course_id FROM guide)` is NULL, and `cs.course_id = NULL` is always FALSE (not NULL-equal). That makes `has_role` correctly false for missing guides without needing a separate WHERE EXISTS guard. The service short-circuits on !guide_exists before inspecting has_role, so the two booleans are independent by contract even though they correlate in this edge case.
func (*Queries) WithTx
func (q *Queries) WithTx(tx pgx.Tx) *Queries
type QuestionType
type QuestionType string
const (
QuestionTypeMultipleChoice QuestionType = "multiple_choice"
QuestionTypeTrueFalse QuestionType = "true_false"
QuestionTypeFreeform QuestionType = "freeform"
)
func (*QuestionType) Scan
func (e *QuestionType) Scan(src interface{}) error
type Quiz
type Quiz struct {
ID pgtype.UUID `json:"id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type QuizAnswerOption
type QuizAnswerOption struct {
ID pgtype.UUID `json:"id"`
QuestionID pgtype.UUID `json:"question_id"`
Text string `json:"text"`
IsCorrect bool `json:"is_correct"`
SortOrder int32 `json:"sort_order"`
}
type QuizQuestion
type QuizQuestion struct {
ID pgtype.UUID `json:"id"`
QuizID pgtype.UUID `json:"quiz_id"`
Type QuestionType `json:"type"`
QuestionText string `json:"question_text"`
Hint pgtype.Text `json:"hint"`
FeedbackCorrect pgtype.Text `json:"feedback_correct"`
FeedbackIncorrect pgtype.Text `json:"feedback_incorrect"`
ReferenceAnswer pgtype.Text `json:"reference_answer"`
IsProtected bool `json:"is_protected"`
SortOrder int32 `json:"sort_order"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type Resource
type Resource struct {
ID pgtype.UUID `json:"id"`
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
Url string `json:"url"`
Description pgtype.Text `json:"description"`
Type ResourceType `json:"type"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type ResourceType
type ResourceType string
const (
ResourceTypeLink ResourceType = "link"
ResourceTypeVideo ResourceType = "video"
ResourceTypeArticle ResourceType = "article"
ResourceTypePdf ResourceType = "pdf"
)
func (*ResourceType) Scan
func (e *ResourceType) Scan(src interface{}) error
type RevokeFileGrantParams
type RevokeFileGrantParams struct {
FileID pgtype.UUID `json:"file_id"`
GranteeType GranteeType `json:"grantee_type"`
GranteeID pgtype.UUID `json:"grantee_id"`
Permission Permission `json:"permission"`
}
type School
type School struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Acronym string `json:"acronym"`
Domain pgtype.Text `json:"domain"`
Url pgtype.Text `json:"url"`
City pgtype.Text `json:"city"`
State pgtype.Text `json:"state"`
Country pgtype.Text `json:"country"`
IpedsID pgtype.Text `json:"ipeds_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type SectionInCourseExistsParams
type SectionInCourseExistsParams struct {
SectionID pgtype.UUID `json:"section_id"`
CourseID pgtype.UUID `json:"course_id"`
}
type SetFileDeletionJobIDParams
type SetFileDeletionJobIDParams struct {
JobID pgtype.Text `json:"job_id"`
FileID pgtype.UUID `json:"file_id"`
}
type SoftDeleteFileParams
type SoftDeleteFileParams struct {
FileID pgtype.UUID `json:"file_id"`
OwnerID pgtype.UUID `json:"owner_id"`
}
type StudyGuide
type StudyGuide struct {
ID pgtype.UUID `json:"id"`
CourseID pgtype.UUID `json:"course_id"`
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Content pgtype.Text `json:"content"`
Tags []string `json:"tags"`
ViewCount int32 `json:"view_count"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type StudyGuideFavorite
type StudyGuideFavorite struct {
UserID pgtype.UUID `json:"user_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type StudyGuideFile
type StudyGuideFile struct {
FileID pgtype.UUID `json:"file_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type StudyGuideLastViewed
type StudyGuideLastViewed struct {
UserID pgtype.UUID `json:"user_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
ViewedAt pgtype.Timestamptz `json:"viewed_at"`
}
type StudyGuideRecommendation
type StudyGuideRecommendation struct {
StudyGuideID pgtype.UUID `json:"study_guide_id"`
RecommendedBy pgtype.UUID `json:"recommended_by"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type StudyGuideResource
type StudyGuideResource struct {
ResourceID pgtype.UUID `json:"resource_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
AttachedBy pgtype.UUID `json:"attached_by"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type StudyGuideVote
type StudyGuideVote struct {
UserID pgtype.UUID `json:"user_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
Vote VoteDirection `json:"vote"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type URLAlreadyAttachedToGuideParams
type URLAlreadyAttachedToGuideParams struct {
StudyGuideID pgtype.UUID `json:"study_guide_id"`
Url string `json:"url"`
}
type UpdateFileParams
type UpdateFileParams struct {
Name string `json:"name"`
FileID pgtype.UUID `json:"file_id"`
OwnerID pgtype.UUID `json:"owner_id"`
}
type UpdateFileRow
type UpdateFileRow struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
Name string `json:"name"`
Size int64 `json:"size"`
MimeType string `json:"mime_type"`
Status UploadStatus `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type UpdateFileStatusParams
type UpdateFileStatusParams struct {
Status UploadStatus `json:"status"`
FileID pgtype.UUID `json:"file_id"`
OwnerID pgtype.UUID `json:"owner_id"`
}
type UpdateQuizParams
type UpdateQuizParams struct {
Title pgtype.Text `json:"title"`
ClearDescription bool `json:"clear_description"`
Description pgtype.Text `json:"description"`
ID pgtype.UUID `json:"id"`
}
type UpdateStudyGuideParams
type UpdateStudyGuideParams struct {
Title pgtype.Text `json:"title"`
Description pgtype.Text `json:"description"`
Content pgtype.Text `json:"content"`
Tags []string `json:"tags"`
ID pgtype.UUID `json:"id"`
}
type UploadStatus
type UploadStatus string
const (
UploadStatusPending UploadStatus = "pending"
UploadStatusComplete UploadStatus = "complete"
UploadStatusFailed UploadStatus = "failed"
)
func (*UploadStatus) Scan
func (e *UploadStatus) Scan(src interface{}) error
type UpsertClerkUserParams
type UpsertClerkUserParams struct {
ClerkID string `json:"clerk_id"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName pgtype.Text `json:"middle_name"`
Metadata interface{} `json:"metadata"`
}
type UpsertFileGrantParams
type UpsertFileGrantParams struct {
FileID pgtype.UUID `json:"file_id"`
GranteeType GranteeType `json:"grantee_type"`
GranteeID pgtype.UUID `json:"grantee_id"`
Permission Permission `json:"permission"`
GrantedBy pgtype.UUID `json:"granted_by"`
}
type UpsertResourceParams
type UpsertResourceParams struct {
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
Url string `json:"url"`
Description pgtype.Text `json:"description"`
Type ResourceType `json:"type"`
}
type UpsertStudyGuideVoteParams
type UpsertStudyGuideVoteParams struct {
UserID pgtype.UUID `json:"user_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
Vote VoteDirection `json:"vote"`
}
type User
type User struct {
ID pgtype.UUID `json:"id"`
ClerkID string `json:"clerk_id"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName pgtype.Text `json:"middle_name"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
Metadata []byte `json:"metadata"`
}
type ViewerCanRecommendForGuideParams
type ViewerCanRecommendForGuideParams struct {
ViewerID pgtype.UUID `json:"viewer_id"`
StudyGuideID pgtype.UUID `json:"study_guide_id"`
}
type ViewerCanRecommendForGuideRow
type ViewerCanRecommendForGuideRow struct {
GuideExists bool `json:"guide_exists"`
HasRole bool `json:"has_role"`
}
type VoteDirection
type VoteDirection string
const (
VoteDirectionUp VoteDirection = "up"
VoteDirectionDown VoteDirection = "down"
)
func (*VoteDirection) Scan
func (e *VoteDirection) Scan(src interface{}) error
Generated by gomarkdoc