From 949a19efc151fc08e9d6d6454173cb58cf3cf181 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Mon, 14 Apr 2025 09:21:13 -0300 Subject: [PATCH] MM-62156: Avoid SELECT * in retention_policy_store.go (#30458) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * MM-62156: Avoid SELECT * in retention_policy_store.go - Modified subQueryIN function to use specific column name instead of SELECT * - Improved code comments to explain the change - Maintained same functionality while avoiding SELECT * Fixes: https://mattermost.atlassian.net/browse/MM-62156 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * simplify subQueryIN comments * inline part of subQueryIN for greater clarity --------- Co-authored-by: Claude Co-authored-by: Mattermost Build --- .../store/sqlstore/retention_policy_store.go | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/server/channels/store/sqlstore/retention_policy_store.go b/server/channels/store/sqlstore/retention_policy_store.go index 87f202abd79..047ea175cc0 100644 --- a/server/channels/store/sqlstore/retention_policy_store.go +++ b/server/channels/store/sqlstore/retention_policy_store.go @@ -642,7 +642,8 @@ func (s *SqlRetentionPolicyStore) RemoveTeams(policyId string, teamIds []string) func subQueryIN(property string, query sq.SelectBuilder) sq.Sqlizer { queryString, args := query.MustSql() - subQuery := fmt.Sprintf("%s IN (SELECT * FROM (%s) AS A)", property, queryString) + + subQuery := fmt.Sprintf("%s IN (%s)", property, queryString) return sq.Expr(subQuery, args...) } @@ -650,11 +651,14 @@ func subQueryIN(property string, query sq.SelectBuilder) sq.Sqlizer { // where a channel or team no longer exists. func (s *SqlRetentionPolicyStore) DeleteOrphanedRows(limit int) (deleted int64, err error) { // We need the extra level of nesting to deal with MySQL's locking - rpcSubQuery := sq.Select("ChannelId"). - From("RetentionPoliciesChannels"). - LeftJoin("Channels ON RetentionPoliciesChannels.ChannelId = Channels.Id"). - Where("Channels.Id IS NULL"). - Limit(uint64(limit)) + rpcSubQuery := sq.Select("ChannelId").FromSelect( + sq.Select("ChannelId"). + From("RetentionPoliciesChannels"). + LeftJoin("Channels ON RetentionPoliciesChannels.ChannelId = Channels.Id"). + Where("Channels.Id IS NULL"). + Limit(uint64(limit)), + "A", + ) rpcDeleteQuery, rpcArgs, err := s.getQueryBuilder(). Delete("RetentionPoliciesChannels"). @@ -664,11 +668,15 @@ func (s *SqlRetentionPolicyStore) DeleteOrphanedRows(limit int) (deleted int64, return int64(0), errors.Wrap(err, "retention_policies_channels_tosql") } - rptSubQuery := sq.Select("TeamId"). - From("RetentionPoliciesTeams"). - LeftJoin("Teams ON RetentionPoliciesTeams.TeamId = Teams.Id"). - Where("Teams.Id IS NULL"). - Limit(uint64(limit)) + // We need the extra level of nesting to deal with MySQL's locking + rptSubQuery := sq.Select("TeamId").FromSelect( + sq.Select("TeamId"). + From("RetentionPoliciesTeams"). + LeftJoin("Teams ON RetentionPoliciesTeams.TeamId = Teams.Id"). + Where("Teams.Id IS NULL"). + Limit(uint64(limit)), + "A", + ) rptDeleteQuery, rptArgs, err := s.getQueryBuilder(). Delete("RetentionPoliciesTeams").