mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
* fix(ws): resolve an empty READ audience for a channel whose row is gone channelReadAudience already failed closed on a GetChannel error; a deleted channel returns (nil, nil) and fell through to the role scan. Return nobody for a missing row too — voice teardown callers union the room's participants and the leaver back in, so their signals still land. Test locks both halves: the non-participant hears nothing, the leaver still gets voice_leave. (OC-0090) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ws): re-elect the key holder in CleanupVoiceForChannel Every other voice-removal path re-elects (finishVoiceLeave, the LiveKit webhook, registerNow, rollbackVoiceJoin, sweepStaleVoiceStates); the channel delete/archive path did not, so a torn-down channel's voiceKeyHolders entry lived for the process lifetime. One updateKeyHolder call at the end of the teardown deletes it. (OC-0012) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ws): implement BroadcastMemberUnban so unban reaches connected clients The admin unban path reaches the hub through an optional-capability type assertion that *ws.Hub never satisfied, so it always missed silently and clients connected during a ban kept the user missing from their member store. Implement the mirror of BroadcastMemberBan: fan out the same member_join a fresh connect sends (clients already map it to addMember), reporting offline since the unbanned user cannot be connected. A compile-time assertion in admin pins the wiring so the assertion can never silently miss again. (OC-0058) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(db): exclude the requester's own flag from the video-cap stream count EnableCameraIfUnderLimit and EnableScreenshareIfUnderLimit counted every stream in the channel including the very flag the UPDATE sets, so a user whose server-side flag was already 1 (client lost track and retried) was refused at the cap against their own stream, with no path out. Subtract the outer row's own bit from the correlated count: re-enable becomes idempotent while the requester's other stream and everyone else's still count. sqlc layer regenerated. (OC-0081) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(ledger): resolve the six blocked batch-4 findings Four fixed in this branch (OC-0012, OC-0058, OC-0081, OC-0090), each with an independent revert-proof pass. Two were already fixed on main by later sibling fixes and are recorded as such: OC-0086 by the OC-0017 pre-delete re-check (#1374), OC-0101 by the OC-0206 early watermark bump (#1375). The ledger holds zero open and zero blocked findings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
277 lines
19 KiB
Go
277 lines
19 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
|
|
package dbgen
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
)
|
|
|
|
type Querier interface {
|
|
AddReaction(ctx context.Context, arg AddReactionParams) error
|
|
AdminUpdateChannel(ctx context.Context, arg AdminUpdateChannelParams) error
|
|
ApplyVoiceServerDeafen(ctx context.Context, arg ApplyVoiceServerDeafenParams) (sql.Result, error)
|
|
// Scoped to channel_id as well as user_id: the moderator's authorization is
|
|
// checked against a channel snapshot several round trips before this write
|
|
// lands, so an unscoped `WHERE user_id = ?` would follow the target onto
|
|
// whatever channel their row points at by then -- including a DM call the
|
|
// moderator was never authorized against (OC-0005). :execresult so the
|
|
// caller can tell a real no-op (target moved) from a normal apply.
|
|
ApplyVoiceServerMute(ctx context.Context, arg ApplyVoiceServerMuteParams) (sql.Result, error)
|
|
BanUser(ctx context.Context, arg BanUserParams) error
|
|
BlockUser(ctx context.Context, arg BlockUserParams) error
|
|
CleanupExpiredLockouts(ctx context.Context, expiresAt string) error
|
|
ClearAllVoiceStates(ctx context.Context) error
|
|
ClearVoiceServerDeafen(ctx context.Context, arg ClearVoiceServerDeafenParams) (sql.Result, error)
|
|
ClearVoiceServerMute(ctx context.Context, arg ClearVoiceServerMuteParams) (sql.Result, error)
|
|
ClearVoiceState(ctx context.Context, userID int64) error
|
|
CloseDM(ctx context.Context, arg CloseDMParams) error
|
|
CountActiveCameras(ctx context.Context, channelID int64) (int64, error)
|
|
CountActiveInvites(ctx context.Context) (int64, error)
|
|
CountActiveMessages(ctx context.Context) (int64, error)
|
|
CountChannels(ctx context.Context) (int64, error)
|
|
CountDMParticipants(ctx context.Context, channelID int64) (int64, error)
|
|
CountRoleMembers(ctx context.Context) ([]CountRoleMembersRow, error)
|
|
CountUsers(ctx context.Context) (int64, error)
|
|
// Authorization probe for the file route: an unlinked attachment is readable by
|
|
// everyone exactly while some user's avatar points at it. Covered by the
|
|
// partial index on users(avatar) added in migration 027.
|
|
CountUsersWithAvatar(ctx context.Context, avatar *string) (int64, error)
|
|
CountUsersWithoutTOTP(ctx context.Context) (int64, error)
|
|
CreateAPIToken(ctx context.Context, arg CreateAPITokenParams) (sql.Result, error)
|
|
CreateAttachment(ctx context.Context, arg CreateAttachmentParams) error
|
|
CreateChannel(ctx context.Context, arg CreateChannelParams) (sql.Result, error)
|
|
CreateEmoji(ctx context.Context, arg CreateEmojiParams) (CreateEmojiRow, error)
|
|
CreateInvite(ctx context.Context, arg CreateInviteParams) error
|
|
CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error)
|
|
CreateRole(ctx context.Context, arg CreateRoleParams) (Role, error)
|
|
CreateUser(ctx context.Context, arg CreateUserParams) (sql.Result, error)
|
|
DeleteChannel(ctx context.Context, id int64) error
|
|
DeleteChannelPermission(ctx context.Context, arg DeleteChannelPermissionParams) error
|
|
DeleteChannelUserPermission(ctx context.Context, arg DeleteChannelUserPermissionParams) error
|
|
DeleteEmoji(ctx context.Context, id int64) (sql.Result, error)
|
|
// Sargable text comparison against idx_sessions_expires_at (migration 031).
|
|
// expires_at is stored as RFC3339 UTC ("2006-01-02T15:04:05Z") and the
|
|
// migration normalized legacy rows, so the caller must pass the cutoff in
|
|
// exactly that layout -- a space-separated cutoff would compare wrong.
|
|
DeleteExpiredSessions(ctx context.Context, expiresAt string) error
|
|
DeleteLockout(ctx context.Context, key string) error
|
|
// Avatars are attachments that are never linked to a message on purpose: the
|
|
// users.avatar URL is what keeps them alive and authorizes serving them
|
|
// (migration 027). Excluding them here is what stops the sweep from destroying
|
|
// every avatar in the instance. idx_users_avatar makes the lookup cheap.
|
|
DeleteOrphanedAttachments(ctx context.Context, uploadedAt string) ([]string, error)
|
|
DeleteOtherSessions(ctx context.Context, arg DeleteOtherSessionsParams) (sql.Result, error)
|
|
DeleteRole(ctx context.Context, id int64) error
|
|
DeleteSessionByID(ctx context.Context, arg DeleteSessionByIDParams) (sql.Result, error)
|
|
DeleteSessionByToken(ctx context.Context, token string) error
|
|
DisablePlugin(ctx context.Context, id int64) error
|
|
EditMessageContent(ctx context.Context, arg EditMessageContentParams) (Message, error)
|
|
// Camera and screenshare share one voice_max_video budget, counted in
|
|
// STREAMS, not rows: a channel capped at N simultaneous video streams must
|
|
// not let a camera publish ignore screenshare occupants (or vice versa,
|
|
// OC-0023), and a single user with both flags set must consume two of the N
|
|
// slots, not one (OC-0006) -- so both gates sum `vs2.camera + vs2.screenshare`
|
|
// across the channel's rows rather than counting rows where either is set.
|
|
// The enabling user's own bit for the flag being set CAN already be 1 at
|
|
// gate time (a client that lost track of the server-side flag retries the
|
|
// enable), so each gate excludes exactly that one bit from the count --
|
|
// see the per-query comments below (OC-0081).
|
|
// The channel-wide stream count excludes the requester's own camera flag
|
|
// (subtracted via the correlated outer-row reference), so re-enabling an
|
|
// already-set camera is idempotent at the cap instead of being refused
|
|
// against the requester's own stream (OC-0081). Their screenshare, and
|
|
// every other user's streams, still count.
|
|
EnableCameraIfUnderLimit(ctx context.Context, arg EnableCameraIfUnderLimitParams) (sql.Result, error)
|
|
EnablePlugin(ctx context.Context, id int64) error
|
|
// Mirror of EnableCameraIfUnderLimit: the count excludes the requester's
|
|
// own screenshare flag so re-enable is idempotent at the cap (OC-0081).
|
|
EnableScreenshareIfUnderLimit(ctx context.Context, arg EnableScreenshareIfUnderLimitParams) (sql.Result, error)
|
|
EvictOldestSessions(ctx context.Context, arg EvictOldestSessionsParams) error
|
|
ForceLogoutUser(ctx context.Context, userID int64) error
|
|
// Auth-hot lookup: returns the token only if it is neither revoked nor expired,
|
|
// so a resolved row is always usable. Matches the sessions never-expiring
|
|
// convention (expires_at IS NULL).
|
|
GetActiveAPIToken(ctx context.Context, tokenHash string) (ApiToken, error)
|
|
GetAllSettings(ctx context.Context) ([]Setting, error)
|
|
GetAllVoiceStates(ctx context.Context) ([]GetAllVoiceStatesRow, error)
|
|
GetAttachmentByID(ctx context.Context, id string) (GetAttachmentByIDRow, error)
|
|
GetAttachmentWithChannel(ctx context.Context, id string) (GetAttachmentWithChannelRow, error)
|
|
GetAuditLog(ctx context.Context, arg GetAuditLogParams) ([]GetAuditLogRow, error)
|
|
GetChannel(ctx context.Context, id int64) (GetChannelRow, error)
|
|
GetChannelOverrides(ctx context.Context, channelID int64) ([]GetChannelOverridesRow, error)
|
|
GetChannelPermission(ctx context.Context, arg GetChannelPermissionParams) (GetChannelPermissionRow, error)
|
|
GetChannelUnreadCounts(ctx context.Context, arg GetChannelUnreadCountsParams) ([]GetChannelUnreadCountsRow, error)
|
|
GetChannelUserOverrides(ctx context.Context, channelID int64) ([]GetChannelUserOverridesRow, error)
|
|
GetChannelUserPermission(ctx context.Context, arg GetChannelUserPermissionParams) (GetChannelUserPermissionRow, error)
|
|
GetChannelVoiceStates(ctx context.Context, channelID int64) ([]GetChannelVoiceStatesRow, error)
|
|
GetDMParticipantIDs(ctx context.Context, channelID int64) ([]int64, error)
|
|
GetDMParticipants(ctx context.Context, channelID int64) ([]GetDMParticipantsRow, error)
|
|
// Every participant of every DM the user has open, in one pass. Includes the
|
|
// user themselves so a caller can tell "group of three" from "group of three
|
|
// others"; the Go layer filters when it needs the others.
|
|
GetDMParticipantsForUser(ctx context.Context, userID int64) ([]GetDMParticipantsForUserRow, error)
|
|
// The fallback role every member lands on when their role is deleted. Highest
|
|
// position wins if a database somehow carries more than one default.
|
|
GetDefaultRole(ctx context.Context) (Role, error)
|
|
GetEmojiByID(ctx context.Context, id int64) (GetEmojiByIDRow, error)
|
|
GetEmojiByShortcode(ctx context.Context, shortcode string) (GetEmojiByShortcodeRow, error)
|
|
GetEventsSince(ctx context.Context, arg GetEventsSinceParams) ([]GetEventsSinceRow, error)
|
|
GetInvite(ctx context.Context, code string) (GetInviteRow, error)
|
|
GetLatestMessageID(ctx context.Context, channelID int64) (interface{}, error)
|
|
GetMaxEventSeq(ctx context.Context) (int64, error)
|
|
GetMessage(ctx context.Context, id int64) (Message, error)
|
|
GetMessagesForAPI(ctx context.Context, arg GetMessagesForAPIParams) ([]GetMessagesForAPIRow, error)
|
|
// The highest-privilege account (role with the greatest position), used as the
|
|
// default identity for `token create`. FROM is users-only (role position is a
|
|
// correlated subquery, not a join) so the row maps through userFromGen exactly
|
|
// like GetUserByID, so keep this SELECT list identical to GetUserByID's.
|
|
// A :one query already reads a single row via QueryRow, so no LIMIT is needed
|
|
// (and an explicit LIMIT 1 is mis-emitted by sqlc here). ORDER BY puts the
|
|
// highest-position role first, so that first row is the owner.
|
|
// Banned users are excluded: account deletion anonymises the row and sets
|
|
// banned = 1 permanently, so without this filter a self-deleted Owner keeps
|
|
// outranking every live admin and becomes the default identity for token
|
|
// creation forever -- minting tokens the auth layer then 403s on every use.
|
|
// The ban_expires arm mirrors auth.IsEffectivelyBanned (and db.notBannedClause)
|
|
// so a lapsed temporary ban stays eligible; the replace() normalises the space
|
|
// separator form of ban_expires to 'T' before comparing, because ' ' sorts
|
|
// below 'T' and a same-day space-form expiry would otherwise read as lapsed.
|
|
GetOwnerUser(ctx context.Context) (User, error)
|
|
GetReactionCounts(ctx context.Context, messageID int64) ([]GetReactionCountsRow, error)
|
|
// Reactors for one (message, emoji) pair, oldest reaction first. The reactions
|
|
// table has no timestamp column, so the autoincrement id carries the order.
|
|
GetReactionUsers(ctx context.Context, arg GetReactionUsersParams) ([]GetReactionUsersRow, error)
|
|
// Reader-pool lookup that lets the channel-focus path skip the UpdateReadState
|
|
// UPSERT when the row is already correct, keeping no-op focus events off the
|
|
// single writer connection.
|
|
GetReadState(ctx context.Context, arg GetReadStateParams) (GetReadStateRow, error)
|
|
GetRoleByID(ctx context.Context, id int64) (Role, error)
|
|
// Case-insensitive by design: migration 023 enforces uniqueness under the same
|
|
// collation, so this is the lookup that agrees with the constraint.
|
|
GetRoleByName(ctx context.Context, name string) (Role, error)
|
|
GetRoleChannelPermissions(ctx context.Context, roleID int64) ([]GetRoleChannelPermissionsRow, error)
|
|
GetRoleForUser(ctx context.Context, id int64) (Role, error)
|
|
GetSessionByTokenHash(ctx context.Context, token string) (Session, error)
|
|
GetSessionWithBanStatus(ctx context.Context, token string) (GetSessionWithBanStatusRow, error)
|
|
GetSetting(ctx context.Context, key string) (string, error)
|
|
GetUserByID(ctx context.Context, id int64) (User, error)
|
|
GetUserByUsername(ctx context.Context, username string) (User, error)
|
|
GetUserChannelPermissions(ctx context.Context, userID int64) ([]GetUserChannelPermissionsRow, error)
|
|
GetUserDMChannelIDs(ctx context.Context, userID int64) ([]int64, error)
|
|
// A DM row carries no recipient any more: dm_participants holds N users, so
|
|
// "the other one" is only well defined for a two-person DM. The participant
|
|
// set comes from GetDMParticipantsForUser below, one extra query for the whole
|
|
// list rather than one per channel, and the Go layer stitches them together.
|
|
GetUserDMChannels(ctx context.Context, userID int64) ([]GetUserDMChannelsRow, error)
|
|
GetUserSessions(ctx context.Context, userID int64) ([]Session, error)
|
|
GetUserVoiceState(ctx context.Context, userID int64) (GetUserVoiceStateRow, error)
|
|
GetUserWithRole(ctx context.Context, id int64) (GetUserWithRoleRow, error)
|
|
InsertSession(ctx context.Context, arg InsertSessionParams) (sql.Result, error)
|
|
InstallPlugin(ctx context.Context, arg InstallPluginParams) (sql.Result, error)
|
|
IsBlocked(ctx context.Context, arg IsBlockedParams) (int64, error)
|
|
IsDMParticipant(ctx context.Context, arg IsDMParticipantParams) (int64, error)
|
|
IsEitherBlocked(ctx context.Context, arg IsEitherBlockedParams) (int64, error)
|
|
IsGroupDM(ctx context.Context, id int64) (int64, error)
|
|
// server_muted / server_deafened are deliberately absent from both upserts'
|
|
// reset lists: a moderator-imposed mute must survive a channel switch, which
|
|
// reaches the ON CONFLICT branch. It is scoped to the voice session:
|
|
// leaving voice deletes the row, so a rejoin starts clean.
|
|
JoinVoiceChannel(ctx context.Context, arg JoinVoiceChannelParams) error
|
|
JoinVoiceChannelIfCapacity(ctx context.Context, arg JoinVoiceChannelIfCapacityParams) (sql.Result, error)
|
|
LeaveVoiceChannel(ctx context.Context, userID int64) error
|
|
LeaveVoiceChannelIfMatch(ctx context.Context, arg LeaveVoiceChannelIfMatchParams) (sql.Result, error)
|
|
// Admin/CLI listing. Never selects token_hash (unrecoverable; only the raw
|
|
// token shown at creation is usable).
|
|
ListAPITokens(ctx context.Context) ([]ListAPITokensRow, error)
|
|
ListAllUsers(ctx context.Context, arg ListAllUsersParams) ([]ListAllUsersRow, error)
|
|
ListBlockedUsers(ctx context.Context, blockerID int64) ([]int64, error)
|
|
ListBlockersOfUser(ctx context.Context, blockedID int64) ([]int64, error)
|
|
ListChannels(ctx context.Context) ([]ListChannelsRow, error)
|
|
ListEmoji(ctx context.Context) ([]ListEmojiRow, error)
|
|
ListInvites(ctx context.Context) ([]ListInvitesRow, error)
|
|
// The ready payload's member roster. docs/protocol.md documents members[] as
|
|
// "All registered users", so this must not silently truncate: the previous
|
|
// LIMIT 1000 dropped every member past the first thousand with no has_more
|
|
// signal, leaving those users unrenderable and unmentionable on the client
|
|
// with nothing to indicate the list was incomplete.
|
|
ListMembers(ctx context.Context) ([]ListMembersRow, error)
|
|
ListPlugins(ctx context.Context) ([]Plugin, error)
|
|
// Highest rank first. Positions are only "unique enough": reorder normalizes
|
|
// them, but creating a role inserts just below the actor and may tie with an
|
|
// existing role, so id is a tiebreaker. Without it SQLite may return tied rows
|
|
// in any order, and the admin panel derives its reorder payload from this
|
|
// order, so a single move-up would silently shuffle the tied roles.
|
|
// NOTE: keep comments in this file ASCII-only. sqlc mixes byte and rune
|
|
// offsets when stripping them, so a non-ASCII character here truncates the
|
|
// generated SQL of THIS and every following query by the byte/rune delta.
|
|
ListRoles(ctx context.Context) ([]Role, error)
|
|
ListUserIDsByRole(ctx context.Context, roleID int64) ([]int64, error)
|
|
ListUserSessions(ctx context.Context, userID int64) ([]Session, error)
|
|
LoadActiveLockouts(ctx context.Context, expiresAt string) ([]RateLockout, error)
|
|
LogAudit(ctx context.Context, arg LogAuditParams) error
|
|
// Disconnect bookkeeping. It clears only 'online', which is the one status
|
|
// that means "has a live session"; idle, dnd and invisible are choices the
|
|
// user made and are what the next connect reads instead of stamping online
|
|
// (db.ConnectStatus). A stale choice never renders as "present" because the
|
|
// read path treats a member with no live connection as offline regardless.
|
|
MarkUserDisconnected(ctx context.Context, id int64) error
|
|
OpenDM(ctx context.Context, arg OpenDMParams) (int64, error)
|
|
// seq is supplied by the hub so the row seq matches the wrapped-payload seq.
|
|
PersistEvent(ctx context.Context, arg PersistEventParams) error
|
|
PluginKVDelete(ctx context.Context, arg PluginKVDeleteParams) error
|
|
PluginKVGet(ctx context.Context, arg PluginKVGetParams) ([]byte, error)
|
|
PluginKVSet(ctx context.Context, arg PluginKVSetParams) error
|
|
PruneEventsOlderThan(ctx context.Context, createdAt time.Time) (int64, error)
|
|
RemoveDMParticipant(ctx context.Context, arg RemoveDMParticipantParams) error
|
|
RemoveReaction(ctx context.Context, arg RemoveReactionParams) (sql.Result, error)
|
|
// Startup reset: nothing is connected yet, so every 'online' is a leftover
|
|
// from the previous process. Chosen statuses survive for the same reason they
|
|
// survive a disconnect.
|
|
ResetAllUserStatuses(ctx context.Context) error
|
|
RevokeAPIToken(ctx context.Context, id int64) (sql.Result, error)
|
|
RevokeAPITokenByLabel(ctx context.Context, label string) (sql.Result, error)
|
|
RevokeInvite(ctx context.Context, code string) error
|
|
SetChannelSlowMode(ctx context.Context, arg SetChannelSlowModeParams) error
|
|
SetChannelVoiceMaxUsers(ctx context.Context, arg SetChannelVoiceMaxUsersParams) error
|
|
SetDMChannelName(ctx context.Context, arg SetDMChannelNameParams) error
|
|
SetMessagePinned(ctx context.Context, arg SetMessagePinnedParams) (sql.Result, error)
|
|
SetRolePosition(ctx context.Context, arg SetRolePositionParams) error
|
|
SetSetting(ctx context.Context, arg SetSettingParams) error
|
|
SoftDeleteMessage(ctx context.Context, id int64) error
|
|
TouchAPIToken(ctx context.Context, tokenHash string) error
|
|
TouchSession(ctx context.Context, token string) error
|
|
UnbanUser(ctx context.Context, id int64) error
|
|
UnblockUser(ctx context.Context, arg UnblockUserParams) error
|
|
UninstallPlugin(ctx context.Context, id int64) error
|
|
UpdateChannel(ctx context.Context, arg UpdateChannelParams) error
|
|
// Marking a channel read also clears its mention badge: channel_focus is the
|
|
// only caller, and a focused channel has no outstanding mentions by definition.
|
|
UpdateReadState(ctx context.Context, arg UpdateReadStateParams) error
|
|
UpdateRole(ctx context.Context, arg UpdateRoleParams) error
|
|
// Separate from UpdateUserProfile because a custom status arrives over the
|
|
// WebSocket presence path, not the REST profile PATCH, and must not be able to
|
|
// clobber the username/avatar of a profile edit racing it.
|
|
UpdateUserCustomStatus(ctx context.Context, arg UpdateUserCustomStatusParams) error
|
|
UpdateUserIdentityKey(ctx context.Context, arg UpdateUserIdentityKeyParams) error
|
|
UpdateUserPassword(ctx context.Context, arg UpdateUserPasswordParams) error
|
|
UpdateUserProfile(ctx context.Context, arg UpdateUserProfileParams) (sql.Result, error)
|
|
UpdateUserRole(ctx context.Context, arg UpdateUserRoleParams) error
|
|
UpdateUserStatus(ctx context.Context, arg UpdateUserStatusParams) error
|
|
UpdateUserTOTPSecret(ctx context.Context, arg UpdateUserTOTPSecretParams) error
|
|
UpdateVoiceCamera(ctx context.Context, arg UpdateVoiceCameraParams) error
|
|
UpdateVoiceDeafen(ctx context.Context, arg UpdateVoiceDeafenParams) error
|
|
UpdateVoiceMute(ctx context.Context, arg UpdateVoiceMuteParams) error
|
|
UpdateVoiceScreenshare(ctx context.Context, arg UpdateVoiceScreenshareParams) error
|
|
UpsertChannelPermission(ctx context.Context, arg UpsertChannelPermissionParams) error
|
|
UpsertChannelUserPermission(ctx context.Context, arg UpsertChannelUserPermissionParams) error
|
|
UpsertLockout(ctx context.Context, arg UpsertLockoutParams) error
|
|
UseInviteAtomic(ctx context.Context, code string) (sql.Result, error)
|
|
UserCount(ctx context.Context) (int64, error)
|
|
}
|
|
|
|
var _ Querier = (*Queries)(nil)
|