bool CPVRDatabase::PersistGroupMembers(const CPVRChannelGroup &group) { bool bReturn = true; bool bRemoveChannels = true; std::string strQuery; CSingleLock lock(group.m_critSection); if (group.HasChannels()) { for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = group.m_sortedMembers.begin(); it != group.m_sortedMembers.end(); ++it) { std::string strWhereClause = PrepareSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u AND iSubChannelNumber = %u", (*it).channel->ChannelID(), group.GroupID(), (*it).iChannelNumber, (*it).iSubChannelNumber); std::string strValue = GetSingleValue("map_channelgroups_channels", "idChannel", strWhereClause); if (strValue.empty()) { strQuery = PrepareSQL("REPLACE INTO map_channelgroups_channels (" "idGroup, idChannel, iChannelNumber, iSubChannelNumber) " "VALUES (%i, %i, %i, %i);", group.GroupID(), (*it).channel->ChannelID(), (*it).iChannelNumber, (*it).iSubChannelNumber); QueueInsertQuery(strQuery); } } lock.Leave(); bReturn = CommitInsertQueries(); bRemoveChannels = RemoveStaleChannelsFromGroup(group); } return bReturn && bRemoveChannels; }
bool CPVRDatabase::PersistGroupMembers(const CPVRChannelGroup &group) { bool bReturn = true; bool bRemoveChannels = true; std::string strQuery; CSingleLock lock(group.m_critSection); if (group.HasChannels()) { for (const auto& groupMember : group.m_sortedMembers) { const std::string strWhereClause = PrepareSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u AND iSubChannelNumber = %u", groupMember.channel->ChannelID(), group.GroupID(), groupMember.channelNumber.GetChannelNumber(), groupMember.channelNumber.GetSubChannelNumber()); const std::string strValue = GetSingleValue("map_channelgroups_channels", "idChannel", strWhereClause); if (strValue.empty()) { strQuery = PrepareSQL("REPLACE INTO map_channelgroups_channels (" "idGroup, idChannel, iChannelNumber, iSubChannelNumber) " "VALUES (%i, %i, %i, %i);", group.GroupID(), groupMember.channel->ChannelID(), groupMember.channelNumber.GetChannelNumber(), groupMember.channelNumber.GetSubChannelNumber()); QueueInsertQuery(strQuery); } } bReturn = CommitInsertQueries(); bRemoveChannels = RemoveStaleChannelsFromGroup(group); } return bReturn && bRemoveChannels; }
bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group) { bool bDelete(true); /* invalid group id */ if (group.GroupID() <= 0) { CLog::Log(LOGERROR, "PVR - %s - invalid group id: %d", __FUNCTION__, group.GroupID()); return false; } if (!group.IsInternalGroup()) { /* First remove channels that don't exist in the main channels table */ // XXX work around for frodo: fix this up so it uses one query for all db types // mysql doesn't support subqueries when deleting and sqlite doesn't support joins when deleting if (StringUtils::EqualsNoCase(g_advancedSettings.m_databaseTV.type, "mysql")) { std::string strQuery = PrepareSQL("DELETE m FROM map_channelgroups_channels m LEFT JOIN channels c ON (c.idChannel = m.idChannel) WHERE c.idChannel IS NULL"); bDelete = ExecuteQuery(strQuery); } else { Filter filter; filter.AppendWhere("idChannel IN (SELECT m.idChannel FROM map_channelgroups_channels m LEFT JOIN channels on m.idChannel = channels.idChannel WHERE channels.idChannel IS NULL)"); bDelete = DeleteValues("map_channelgroups_channels", filter); } } if (group.HasChannels()) { std::vector<int> currentMembers; if (GetCurrentGroupMembers(group, currentMembers)) { std::vector<int> channelsToDelete; for (unsigned int iChannelPtr = 0; iChannelPtr < currentMembers.size(); iChannelPtr++) { if (!group.IsGroupMember(currentMembers.at(iChannelPtr))) channelsToDelete.push_back(currentMembers.at(iChannelPtr)); } bDelete = DeleteChannelsFromGroup(group, channelsToDelete) && bDelete; } } else { Filter filter; filter.AppendWhere(PrepareSQL("idGroup = %u", group.GroupID())); bDelete = DeleteValues("map_channelgroups_channels", filter) && bDelete; } return bDelete; }
bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group) { bool bDelete(true); /* invalid group id */ if (group.GroupID() <= 0) { CLog::LogF(LOGERROR, "Invalid channel group id: %d", group.GroupID()); return false; } CSingleLock lock(m_critSection); if (!group.IsInternalGroup()) { /* First remove channels that don't exist in the main channels table */ // XXX work around for frodo: fix this up so it uses one query for all db types // mysql doesn't support subqueries when deleting and sqlite doesn't support joins when deleting if (StringUtils::EqualsNoCase(g_advancedSettings.m_databaseTV.type, "mysql")) { const std::string strQuery = PrepareSQL("DELETE m FROM map_channelgroups_channels m LEFT JOIN channels c ON (c.idChannel = m.idChannel) WHERE c.idChannel IS NULL"); bDelete = ExecuteQuery(strQuery); } else { Filter filter; filter.AppendWhere("idChannel IN (SELECT m.idChannel FROM map_channelgroups_channels m LEFT JOIN channels on m.idChannel = channels.idChannel WHERE channels.idChannel IS NULL)"); bDelete = DeleteValues("map_channelgroups_channels", filter); } } if (group.HasChannels()) { std::vector<int> currentMembers; if (GetCurrentGroupMembers(group, currentMembers)) { std::vector<int> channelsToDelete; for (int iChannelId : currentMembers) { if (!group.IsGroupMember(iChannelId)) { int iClientId = GetClientIdByChannelId(iChannelId); if (iClientId == PVR_INVALID_CLIENT_ID || !group.IsMissingChannelsFromClient(iClientId)) { channelsToDelete.emplace_back(iChannelId); } } } if (!channelsToDelete.empty()) bDelete = DeleteChannelsFromGroup(group, channelsToDelete) && bDelete; } } else { Filter filter; filter.AppendWhere(PrepareSQL("idGroup = %u", group.GroupID())); bDelete = DeleteValues("map_channelgroups_channels", filter) && bDelete; } return bDelete; }