Query automatically does ToSlice. Use QueryIterator if you need an
iterator.
This commit is contained in:
parent
c84b6842e2
commit
b5eb718615
13
src/db/db.go
13
src/db/db.go
|
@ -231,7 +231,16 @@ func followPathThroughStructs(structPtrVal reflect.Value, path []int) (reflect.V
|
|||
return val, field
|
||||
}
|
||||
|
||||
func Query(ctx context.Context, conn ConnOrTx, destExample interface{}, query string, args ...interface{}) (*StructQueryIterator, error) {
|
||||
func Query(ctx context.Context, conn ConnOrTx, destExample interface{}, query string, args ...interface{}) ([]interface{}, error) {
|
||||
it, err := QueryIterator(ctx, conn, destExample, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return it.ToSlice(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func QueryIterator(ctx context.Context, conn ConnOrTx, destExample interface{}, query string, args ...interface{}) (*StructQueryIterator, error) {
|
||||
destType := reflect.TypeOf(destExample)
|
||||
columnNames, fieldPaths, err := getColumnNamesAndPaths(destType, nil, "")
|
||||
if err != nil {
|
||||
|
@ -347,7 +356,7 @@ result but find nothing.
|
|||
var NotFound = errors.New("not found")
|
||||
|
||||
func QueryOne(ctx context.Context, conn ConnOrTx, destExample interface{}, query string, args ...interface{}) (interface{}, error) {
|
||||
rows, err := Query(ctx, conn, destExample, query, args...)
|
||||
rows, err := QueryIterator(ctx, conn, destExample, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ func (bot *botInstance) doSender(ctx context.Context) {
|
|||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
itMessages, err := db.Query(ctx, tx, models.DiscordOutgoingMessage{}, `
|
||||
msgs, err := db.Query(ctx, tx, models.DiscordOutgoingMessage{}, `
|
||||
SELECT $columns
|
||||
FROM discord_outgoingmessages
|
||||
ORDER BY id ASC
|
||||
|
@ -418,7 +418,6 @@ func (bot *botInstance) doSender(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
msgs := itMessages.ToSlice()
|
||||
for _, imsg := range msgs {
|
||||
msg := imsg.(*models.DiscordOutgoingMessage)
|
||||
if time.Now().After(msg.ExpiresAt) {
|
||||
|
|
|
@ -64,7 +64,7 @@ func fetchMissingContent(ctx context.Context, dbConn *pgxpool.Pool) {
|
|||
type query struct {
|
||||
Message models.DiscordMessage `db:"msg"`
|
||||
}
|
||||
result, err := db.Query(ctx, dbConn, query{},
|
||||
imessagesWithoutContent, err := db.Query(ctx, dbConn, query{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM
|
||||
|
@ -82,7 +82,6 @@ func fetchMissingContent(ctx context.Context, dbConn *pgxpool.Pool) {
|
|||
log.Error().Err(err).Msg("failed to check for messages without content")
|
||||
return
|
||||
}
|
||||
imessagesWithoutContent := result.ToSlice()
|
||||
|
||||
if len(imessagesWithoutContent) > 0 {
|
||||
log.Info().Msgf("There are %d Discord messages without content, fetching their content now...", len(imessagesWithoutContent))
|
||||
|
|
|
@ -749,7 +749,7 @@ func UpdateSnippetTagsIfAny(ctx context.Context, dbConn db.ConnOrTx, msg *Messag
|
|||
type tagsRow struct {
|
||||
Tag models.Tag `db:"tags"`
|
||||
}
|
||||
itUserTags, err := db.Query(ctx, tx, tagsRow{},
|
||||
iUserTags, err := db.Query(ctx, tx, tagsRow{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM
|
||||
|
@ -764,7 +764,6 @@ func UpdateSnippetTagsIfAny(ctx context.Context, dbConn db.ConnOrTx, msg *Messag
|
|||
if err != nil {
|
||||
return oops.New(err, "failed to fetch tags for user projects")
|
||||
}
|
||||
iUserTags := itUserTags.ToSlice()
|
||||
|
||||
var tagIDs []int
|
||||
for _, itag := range iUserTags {
|
||||
|
@ -805,7 +804,7 @@ var RESnippetableUrl = regexp.MustCompile(`^https?://(youtu\.be|(www\.)?youtube\
|
|||
|
||||
func getSnippetAssetOrUrl(ctx context.Context, tx db.ConnOrTx, msg *models.DiscordMessage) (*uuid.UUID, *string, error) {
|
||||
// Check attachments
|
||||
itAttachments, err := db.Query(ctx, tx, models.DiscordMessageAttachment{},
|
||||
attachments, err := db.Query(ctx, tx, models.DiscordMessageAttachment{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM handmade_discordmessageattachment
|
||||
|
@ -816,14 +815,13 @@ func getSnippetAssetOrUrl(ctx context.Context, tx db.ConnOrTx, msg *models.Disco
|
|||
if err != nil {
|
||||
return nil, nil, oops.New(err, "failed to fetch message attachments")
|
||||
}
|
||||
attachments := itAttachments.ToSlice()
|
||||
for _, iattachment := range attachments {
|
||||
attachment := iattachment.(*models.DiscordMessageAttachment)
|
||||
return &attachment.AssetID, nil, nil
|
||||
}
|
||||
|
||||
// Check embeds
|
||||
itEmbeds, err := db.Query(ctx, tx, models.DiscordMessageEmbed{},
|
||||
embeds, err := db.Query(ctx, tx, models.DiscordMessageEmbed{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM handmade_discordmessageembed
|
||||
|
@ -834,7 +832,6 @@ func getSnippetAssetOrUrl(ctx context.Context, tx db.ConnOrTx, msg *models.Disco
|
|||
if err != nil {
|
||||
return nil, nil, oops.New(err, "failed to fetch discord embeds")
|
||||
}
|
||||
embeds := itEmbeds.ToSlice()
|
||||
for _, iembed := range embeds {
|
||||
embed := iembed.(*models.DiscordMessageEmbed)
|
||||
if embed.VideoID != nil {
|
||||
|
|
|
@ -145,11 +145,10 @@ func FetchProjects(
|
|||
}
|
||||
|
||||
// Do the query
|
||||
itProjects, err := db.Query(ctx, dbConn, projectRow{}, qb.String(), qb.Args()...)
|
||||
iprojects, err := db.Query(ctx, dbConn, projectRow{}, qb.String(), qb.Args()...)
|
||||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch projects")
|
||||
}
|
||||
iprojects := itProjects.ToSlice()
|
||||
|
||||
// Fetch project owners to do permission checks
|
||||
projectIds := make([]int, len(iprojects))
|
||||
|
@ -340,7 +339,7 @@ func FetchMultipleProjectsOwners(
|
|||
UserID int `db:"user_id"`
|
||||
ProjectID int `db:"project_id"`
|
||||
}
|
||||
it, err := db.Query(ctx, tx, userProject{},
|
||||
iuserprojects, err := db.Query(ctx, tx, userProject{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM handmade_user_projects
|
||||
|
@ -351,7 +350,6 @@ func FetchMultipleProjectsOwners(
|
|||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch project IDs")
|
||||
}
|
||||
iuserprojects := it.ToSlice()
|
||||
|
||||
// Get the unique user IDs from this set and fetch the users from the db
|
||||
var userIds []int
|
||||
|
@ -368,7 +366,7 @@ func FetchMultipleProjectsOwners(
|
|||
userIds = append(userIds, userProject.UserID)
|
||||
}
|
||||
}
|
||||
it, err = db.Query(ctx, tx, models.User{},
|
||||
iusers, err := db.Query(ctx, tx, models.User{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM auth_user
|
||||
|
@ -380,7 +378,6 @@ func FetchMultipleProjectsOwners(
|
|||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch users for projects")
|
||||
}
|
||||
iusers := it.ToSlice()
|
||||
|
||||
// Build the final result set with real user data
|
||||
res := make([]ProjectOwners, len(projectIds))
|
||||
|
|
|
@ -47,7 +47,7 @@ func FetchSnippets(
|
|||
type snippetIDRow struct {
|
||||
SnippetID int `db:"snippet_id"`
|
||||
}
|
||||
itSnippetIDs, err := db.Query(ctx, tx, snippetIDRow{},
|
||||
iSnippetIDs, err := db.Query(ctx, tx, snippetIDRow{},
|
||||
`
|
||||
SELECT DISTINCT snippet_id
|
||||
FROM
|
||||
|
@ -61,7 +61,6 @@ func FetchSnippets(
|
|||
if err != nil {
|
||||
return nil, oops.New(err, "failed to get snippet IDs for tag")
|
||||
}
|
||||
iSnippetIDs := itSnippetIDs.ToSlice()
|
||||
|
||||
// special early-out: no snippets found for these tags at all
|
||||
if len(iSnippetIDs) == 0 {
|
||||
|
@ -125,11 +124,10 @@ func FetchSnippets(
|
|||
DiscordMessage *models.DiscordMessage `db:"discord_message"`
|
||||
}
|
||||
|
||||
it, err := db.Query(ctx, tx, resultRow{}, qb.String(), qb.Args()...)
|
||||
iresults, err := db.Query(ctx, tx, resultRow{}, qb.String(), qb.Args()...)
|
||||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch threads")
|
||||
}
|
||||
iresults := it.ToSlice()
|
||||
|
||||
result := make([]SnippetAndStuff, len(iresults)) // allocate extra space because why not
|
||||
snippetIDs := make([]int, len(iresults))
|
||||
|
@ -151,7 +149,7 @@ func FetchSnippets(
|
|||
SnippetID int `db:"snippet_tags.snippet_id"`
|
||||
Tag *models.Tag `db:"tags"`
|
||||
}
|
||||
itSnippetTags, err := db.Query(ctx, tx, snippetTagRow{},
|
||||
iSnippetTags, err := db.Query(ctx, tx, snippetTagRow{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM
|
||||
|
@ -165,7 +163,6 @@ func FetchSnippets(
|
|||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch tags for snippets")
|
||||
}
|
||||
iSnippetTags := itSnippetTags.ToSlice()
|
||||
|
||||
// associate tags with snippets
|
||||
resultBySnippetId := make(map[int]*SnippetAndStuff)
|
||||
|
|
|
@ -40,11 +40,10 @@ func FetchTags(ctx context.Context, dbConn db.ConnOrTx, q TagQuery) ([]*models.T
|
|||
qb.Add(`LIMIT $? OFFSET $?`, q.Limit, q.Offset)
|
||||
}
|
||||
|
||||
it, err := db.Query(ctx, dbConn, models.Tag{}, qb.String(), qb.Args()...)
|
||||
itags, err := db.Query(ctx, dbConn, models.Tag{}, qb.String(), qb.Args()...)
|
||||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch tags")
|
||||
}
|
||||
itags := it.ToSlice()
|
||||
|
||||
res := make([]*models.Tag, len(itags))
|
||||
for i, itag := range itags {
|
||||
|
|
|
@ -143,11 +143,10 @@ func FetchThreads(
|
|||
ForumLastReadTime *time.Time `db:"slri.lastread"`
|
||||
}
|
||||
|
||||
it, err := db.Query(ctx, dbConn, resultRow{}, qb.String(), qb.Args()...)
|
||||
iresults, err := db.Query(ctx, dbConn, resultRow{}, qb.String(), qb.Args()...)
|
||||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch threads")
|
||||
}
|
||||
iresults := it.ToSlice()
|
||||
|
||||
result := make([]ThreadAndStuff, len(iresults))
|
||||
for i, iresult := range iresults {
|
||||
|
@ -398,11 +397,10 @@ func FetchPosts(
|
|||
qb.Add(`LIMIT $? OFFSET $?`, q.Limit, q.Offset)
|
||||
}
|
||||
|
||||
it, err := db.Query(ctx, dbConn, resultRow{}, qb.String(), qb.Args()...)
|
||||
iresults, err := db.Query(ctx, dbConn, resultRow{}, qb.String(), qb.Args()...)
|
||||
if err != nil {
|
||||
return nil, oops.New(err, "failed to fetch posts")
|
||||
}
|
||||
iresults := it.ToSlice()
|
||||
|
||||
result := make([]PostAndStuff, len(iresults))
|
||||
for i, iresult := range iresults {
|
||||
|
@ -856,7 +854,7 @@ func CreatePostVersion(ctx context.Context, tx pgx.Tx, postId int, unparsedConte
|
|||
|
||||
var values [][]interface{}
|
||||
|
||||
for _, asset := range assetResult.ToSlice() {
|
||||
for _, asset := range assetResult {
|
||||
values = append(values, []interface{}{postId, asset.(*assetId).AssetID})
|
||||
}
|
||||
|
||||
|
@ -892,7 +890,7 @@ func FixThreadPostIds(ctx context.Context, tx pgx.Tx, threadId int) error {
|
|||
}
|
||||
|
||||
var firstPost, lastPost *models.Post
|
||||
for _, ipost := range postsIter.ToSlice() {
|
||||
for _, ipost := range postsIter {
|
||||
post := ipost.(*models.Post)
|
||||
|
||||
if firstPost == nil || post.PostDate.Before(firstPost.PostDate) {
|
||||
|
|
|
@ -47,7 +47,7 @@ func GetFullSubforumTree(ctx context.Context, conn *pgxpool.Pool) SubforumTree {
|
|||
type subforumRow struct {
|
||||
Subforum Subforum `db:"sf"`
|
||||
}
|
||||
rows, err := db.Query(ctx, conn, subforumRow{},
|
||||
rowsSlice, err := db.Query(ctx, conn, subforumRow{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM
|
||||
|
@ -59,7 +59,6 @@ func GetFullSubforumTree(ctx context.Context, conn *pgxpool.Pool) SubforumTree {
|
|||
panic(oops.New(err, "failed to fetch subforum tree"))
|
||||
}
|
||||
|
||||
rowsSlice := rows.ToSlice()
|
||||
sfTreeMap := make(map[int]*SubforumTreeNode, len(rowsSlice))
|
||||
for _, row := range rowsSlice {
|
||||
sf := row.(*subforumRow).Subforum
|
||||
|
|
|
@ -253,7 +253,7 @@ func fetchUnapprovedPosts(c *RequestContext) ([]*UnapprovedPost, error) {
|
|||
return nil, oops.New(err, "failed to fetch unapproved posts")
|
||||
}
|
||||
var res []*UnapprovedPost
|
||||
for _, iresult := range it.ToSlice() {
|
||||
for _, iresult := range it {
|
||||
res = append(res, iresult.(*UnapprovedPost))
|
||||
}
|
||||
return res, nil
|
||||
|
@ -285,7 +285,7 @@ func deleteAllPostsForUser(ctx context.Context, conn *pgxpool.Pool, userId int)
|
|||
return oops.New(err, "failed to fetch posts to delete for user")
|
||||
}
|
||||
|
||||
for _, iResult := range it.ToSlice() {
|
||||
for _, iResult := range it {
|
||||
row := iResult.(*toDelete)
|
||||
hmndata.DeletePost(ctx, tx, row.ThreadID, row.PostID)
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ func DiscordShowcaseBacklog(c *RequestContext) ResponseData {
|
|||
type messageIdQuery struct {
|
||||
MessageID string `db:"msg.id"`
|
||||
}
|
||||
itMsgIds, err := db.Query(c.Context(), c.Conn, messageIdQuery{},
|
||||
iMsgIDs, err := db.Query(c.Context(), c.Conn, messageIdQuery{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM
|
||||
|
@ -169,7 +169,9 @@ func DiscordShowcaseBacklog(c *RequestContext) ResponseData {
|
|||
duser.UserID,
|
||||
config.Config.Discord.ShowcaseChannelID,
|
||||
)
|
||||
iMsgIDs := itMsgIds.ToSlice()
|
||||
if err != nil {
|
||||
return c.ErrorResponse(http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
var msgIDs []string
|
||||
for _, imsgId := range iMsgIDs {
|
||||
|
|
|
@ -573,7 +573,7 @@ func FetchPodcast(c *RequestContext, projectId int, fetchEpisodes bool, episodeG
|
|||
if err != nil {
|
||||
return result, oops.New(err, "failed to fetch podcast episodes")
|
||||
}
|
||||
for _, episodeRow := range podcastEpisodeQueryResult.ToSlice() {
|
||||
for _, episodeRow := range podcastEpisodeQueryResult {
|
||||
result.Episodes = append(result.Episodes, &episodeRow.(*podcastEpisodeQuery).Episode)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -323,15 +323,15 @@ func ProjectHomepage(c *RequestContext) ResponseData {
|
|||
}
|
||||
}
|
||||
|
||||
for _, screenshot := range screenshotQueryResult.ToSlice() {
|
||||
for _, screenshot := range screenshotQueryResult {
|
||||
templateData.Screenshots = append(templateData.Screenshots, hmnurl.BuildUserFile(screenshot.(*screenshotQuery).Filename))
|
||||
}
|
||||
|
||||
for _, link := range projectLinkResult.ToSlice() {
|
||||
for _, link := range projectLinkResult {
|
||||
templateData.ProjectLinks = append(templateData.ProjectLinks, templates.LinkToTemplate(&link.(*projectLinkQuery).Link))
|
||||
}
|
||||
|
||||
for _, post := range postQueryResult.ToSlice() {
|
||||
for _, post := range postQueryResult {
|
||||
templateData.RecentActivity = append(templateData.RecentActivity, PostToTimelineItem(
|
||||
c.UrlContext,
|
||||
lineageBuilder,
|
||||
|
@ -801,7 +801,7 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
|
|||
}
|
||||
}
|
||||
|
||||
ownerResult, err := db.Query(ctx, tx, models.User{},
|
||||
ownerRows, err := db.Query(ctx, tx, models.User{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM auth_user
|
||||
|
@ -812,7 +812,6 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
|
|||
if err != nil {
|
||||
return oops.New(err, "Failed to query users")
|
||||
}
|
||||
ownerRows := ownerResult.ToSlice()
|
||||
|
||||
_, err = tx.Exec(ctx,
|
||||
`
|
||||
|
|
|
@ -85,7 +85,7 @@ func UserProfile(c *RequestContext) ResponseData {
|
|||
type userLinkQuery struct {
|
||||
UserLink models.Link `db:"link"`
|
||||
}
|
||||
userLinkQueryResult, err := db.Query(c.Context(), c.Conn, userLinkQuery{},
|
||||
userLinksSlice, err := db.Query(c.Context(), c.Conn, userLinkQuery{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM
|
||||
|
@ -99,7 +99,6 @@ func UserProfile(c *RequestContext) ResponseData {
|
|||
if err != nil {
|
||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch links for user: %s", username))
|
||||
}
|
||||
userLinksSlice := userLinkQueryResult.ToSlice()
|
||||
profileUserLinks := make([]templates.Link, 0, len(userLinksSlice))
|
||||
for _, l := range userLinksSlice {
|
||||
profileUserLinks = append(profileUserLinks, templates.LinkToTemplate(&l.(*userLinkQuery).UserLink))
|
||||
|
@ -223,7 +222,7 @@ func UserSettings(c *RequestContext) ResponseData {
|
|||
DiscordShowcaseBacklogUrl string
|
||||
}
|
||||
|
||||
ilinks, err := db.Query(c.Context(), c.Conn, models.Link{},
|
||||
links, err := db.Query(c.Context(), c.Conn, models.Link{},
|
||||
`
|
||||
SELECT $columns
|
||||
FROM handmade_links
|
||||
|
@ -235,7 +234,6 @@ func UserSettings(c *RequestContext) ResponseData {
|
|||
if err != nil {
|
||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user links"))
|
||||
}
|
||||
links := ilinks.ToSlice()
|
||||
|
||||
linksText := ""
|
||||
for _, ilink := range links {
|
||||
|
|
Loading…
Reference in New Issue