From b67dba9f26104e6ce6cd505adeaff0b4cd0bc41e Mon Sep 17 00:00:00 2001 From: biast12 Date: Fri, 19 Dec 2025 15:09:21 +0100 Subject: [PATCH] Add count query support to TicketTable Introduced CountByOptions method and BuildCountQuery to enable counting tickets based on query options. This allows efficient retrieval of ticket counts matching various filters without fetching full ticket data. --- tickets.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/tickets.go b/tickets.go index 0215cd5..d6ab3b9 100644 --- a/tickets.go +++ b/tickets.go @@ -255,6 +255,21 @@ func (t *TicketTable) GetByOptions(ctx context.Context, options TicketQueryOptio return } +func (t *TicketTable) CountByOptions(ctx context.Context, options TicketQueryOptions) (int, error) { + query, args, err := options.BuildCountQuery() + if err != nil { + return 0, err + } + + var count int + err = t.QueryRow(ctx, query, args...).Scan(&count) + if err != nil { + return 0, err + } + + return count, nil +} + func (o TicketQueryOptions) BuildQuery() (query string, args []interface{}, _err error) { query = ` SELECT tickets.id, @@ -391,6 +406,112 @@ FROM tickets` return } +func (o TicketQueryOptions) BuildCountQuery() (query string, args []interface{}, _err error) { + query = "SELECT COUNT(*) FROM tickets" + + if o.Rating != 0 { + query += " INNER JOIN service_ratings ON tickets.guild_id = service_ratings.guild_id AND tickets.id = service_ratings.ticket_id " + } + + if o.ClosedById != 0 { + query += " INNER JOIN close_reason ON tickets.guild_id = close_reason.guild_id AND tickets.id = close_reason.ticket_id " + } + + if o.ClaimedById != 0 { + query += " INNER JOIN ticket_claims ON tickets.guild_id = ticket_claims.guild_id AND tickets.id = ticket_claims.ticket_id " + } + + if !o.HasWhereClause() { + query += " WHERE " + } + + var needsAnd bool + + if o.Id != 0 { + args = append(args, o.Id) + query += fmt.Sprintf(`tickets.id = $%d`, len(args)) + needsAnd = true + } + + if o.GuildId != 0 { + if needsAnd { + query += " AND " + } + + args = append(args, o.GuildId) + query += fmt.Sprintf(`tickets.guild_id = $%d`, len(args)) + needsAnd = true + } + + if o.ClosedById != 0 { + if needsAnd { + query += " AND " + } + + args = append(args, o.ClosedById) + query += fmt.Sprintf(`close_reason.closed_by = $%d`, len(args)) + needsAnd = true + } + + if o.ClaimedById != 0 { + if needsAnd { + query += " AND " + } + + args = append(args, o.ClaimedById) + query += fmt.Sprintf(`ticket_claims.user_id = $%d`, len(args)) + needsAnd = true + } + + if len(o.UserIds) > 0 { + if needsAnd { + query += " AND " + } + + userIdArray := &pgtype.Int8Array{} + if err := userIdArray.Set(o.UserIds); err != nil { + return "", nil, err + } + + args = append(args, userIdArray) + query += fmt.Sprintf(`tickets.user_id = ANY($%d)`, len(args)) + needsAnd = true + } + + if o.Open != nil { + if needsAnd { + query += " AND " + } + + args = append(args, *o.Open) + query += fmt.Sprintf(`tickets.open = $%d`, len(args)) + needsAnd = true + } + + if o.PanelId > 0 { + if needsAnd { + query += " AND " + } + + args = append(args, o.PanelId) + query += fmt.Sprintf(`tickets.panel_id = $%d`, len(args)) + needsAnd = true + } + + if o.Rating > 0 { + if needsAnd { + query += " AND " + } + + args = append(args, o.Rating) + query += fmt.Sprintf(`service_ratings.rating = $%d`, len(args)) + needsAnd = true + } + + query += ";" + return +} + func (t *TicketTable) GetByChannel(ctx context.Context, channelId uint64) (Ticket, bool, error) { query := ` SELECT id, guild_id, channel_id, user_id, open, open_time, welcome_message_id, panel_id, has_transcript, close_time, is_thread, join_message_id, notes_thread_id, status