Refactor parent thread SQL to use a CTE (one query rather than several)

This commit is contained in:
Alessio 2023-08-04 15:36:41 -03:00
parent 3c3fd55991
commit bb6a7738ba

View File

@ -1,7 +1,6 @@
package persistence package persistence
import ( import (
"database/sql"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
@ -175,51 +174,42 @@ func NewTweetDetailView() TweetDetailView {
func (p Profile) GetTweetDetail(id TweetID) (TweetDetailView, error) { func (p Profile) GetTweetDetail(id TweetID) (TweetDetailView, error) {
// TODO: compound-query-structs // TODO: compound-query-structs
ret := NewTweetDetailView() ret := NewTweetDetailView()
ret.MainTweetID = id
stmt, err := p.DB.Preparex( stmt, err := p.DB.Preparex(`
`select id, user_id, text, posted_at, num_likes, num_retweets, num_replies, num_quote_tweets, in_reply_to_id, quoted_tweet_id, with recursive all_replies(id) as (values(?) union all
mentions, reply_mentions, hashtags, ifnull(space_id, '') space_id, ifnull(tombstone_types.short_name, "") tombstone_type, select tweets.in_reply_to_id from tweets, all_replies
is_expandable, where tweets.id = all_replies.id and tweets.in_reply_to_id != 0
)
select tweets.id id, user_id, text, posted_at, num_likes, num_retweets, num_replies, num_quote_tweets, in_reply_to_id,
quoted_tweet_id, mentions, reply_mentions, hashtags, ifnull(space_id, '') space_id,
ifnull(tombstone_types.short_name, "") tombstone_type, is_expandable,
is_stub, is_content_downloaded, is_conversation_scraped, last_scraped_at is_stub, is_content_downloaded, is_conversation_scraped, last_scraped_at
from tweets from tweets
left join tombstone_types on tweets.tombstone_type = tombstone_types.rowid left join tombstone_types on tweets.tombstone_type = tombstone_types.rowid
where id = ?`) inner join all_replies on tweets.id = all_replies.id
order by id asc`)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Main tweet // Main tweet and parents
var tweet Tweet var thread []Tweet
err = stmt.Get(&tweet, id) err = stmt.Select(&thread, id)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { panic(err)
}
if len(thread) == 0 {
return ret, fmt.Errorf("Tweet ID %d: %w", id, ErrNotInDB) return ret, fmt.Errorf("Tweet ID %d: %w", id, ErrNotInDB)
} else {
panic(err)
}
} }
for _, tweet := range thread {
ret.Tweets[tweet.ID] = tweet ret.Tweets[tweet.ID] = tweet
ret.MainTweetID = tweet.ID if tweet.ID != ret.MainTweetID {
ret.ParentIDs = append(ret.ParentIDs, tweet.ID)
// Parent tweets
for tweet.InReplyToID != 0 {
err := stmt.Get(&tweet, tweet.InReplyToID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
break
} else {
panic(err)
} }
} }
ret.Tweets[tweet.ID] = tweet
ret.ParentIDs = append([]TweetID{tweet.ID}, ret.ParentIDs...)
}
// TODO: tweet-detail-thread-chains
// Replies lvl 1
// TODO: this can be done with a recursive Common Table Expression:
// - https://www.sqlite.org/lang_with.html#recursive_query_examples
var replies []Tweet var replies []Tweet
stmt, err = p.DB.Preparex( stmt, err = p.DB.Preparex(
`select id, user_id, text, posted_at, num_likes, num_retweets, num_replies, num_quote_tweets, in_reply_to_id, quoted_tweet_id, `select id, user_id, text, posted_at, num_likes, num_retweets, num_replies, num_quote_tweets, in_reply_to_id, quoted_tweet_id,