From e5bb0fb5a69c6cf02264242b7f11ed52646b83a6 Mon Sep 17 00:00:00 2001 From: Andrea Gianarda <andrea.gianarda@belledonne-communications.com> Date: Tue, 19 Sep 2023 10:11:38 +0200 Subject: [PATCH] - Add table conference_info_participant_params to store participant parameters instead of putting them as a string in conference_info_participant Change participant role from Unknown to Speaker during the migration - Do not use table conference_info_organizer anymore and move its content to table conference_info_participant - Delete MainDbPrivate::selectConferenceCallEvent as unused --- src/db/internal/statements.cpp | 2 +- src/db/main-db-p.h | 17 +- src/db/main-db.cpp | 396 ++++++++++++--------- tester/local_conference_edition_tester.cpp | 2 +- 4 files changed, 233 insertions(+), 184 deletions(-) diff --git a/src/db/internal/statements.cpp b/src/db/internal/statements.cpp index 380c93574c..f58ab8d38f 100644 --- a/src/db/internal/statements.cpp +++ b/src/db/internal/statements.cpp @@ -124,7 +124,7 @@ constexpr const char *select[SelectCount] = { /* SelectConferenceInfoParticipantId */ R"( SELECT id FROM conference_info_participant - WHERE conference_info_id = :1 AND participant_sip_address_id = :2 + WHERE conference_info_id = :1 AND participant_sip_address_id = :2 and is_organizer = :3 )", /* SelectConferenceInfoOrganizerId */ R"( diff --git a/src/db/main-db-p.h b/src/db/main-db-p.h index 2a1f08847c..ae6f571324 100644 --- a/src/db/main-db-p.h +++ b/src/db/main-db-p.h @@ -69,15 +69,23 @@ private: const std::string &deviceName); void insertChatMessageParticipant(long long chatMessageId, long long sipAddressId, int state, time_t stateChangeTime); + ParticipantInfo::participant_params_t selectConferenceInfoParticipantParams(const long long participantId) const; + ParticipantInfo::participant_params_t + migrateConferenceInfoParticipantParams(const ParticipantInfo::participant_params_t &unprocessedParticipantParams, + const long long participantId) const; long long insertConferenceInfo(const std::shared_ptr<ConferenceInfo> &conferenceInfo, const std::shared_ptr<ConferenceInfo> &oldConferenceInfo); long long insertOrUpdateConferenceInfoParticipant(long long conferenceInfoId, long long participantSipAddressId, bool deleted, - const ParticipantInfo::participant_params_t params); + const ParticipantInfo::participant_params_t params, + bool isOrganizer); long long insertOrUpdateConferenceInfoOrganizer(long long conferenceInfoId, long long organizerSipAddressId, const ParticipantInfo::participant_params_t params); + void insertOrUpdateConferenceInfoParticipantParams(long long conferenceInfoParticipantId, + const ParticipantInfo::participant_params_t params); + long long insertOrUpdateConferenceCall(const std::shared_ptr<CallLog> &callLog, const std::shared_ptr<ConferenceInfo> &conferenceInfo = nullptr); @@ -89,8 +97,9 @@ private: long long selectChatRoomParticipantId(long long chatRoomId, long long participantSipAddressId) const; long long selectOneToOneChatRoomId(long long sipAddressIdA, long long sipAddressIdB, bool encrypted) const; long long selectConferenceInfoId(long long uriSipAddressId); - long long selectConferenceInfoParticipantId(long long conferenceInfoId, long long participantSipAddressId) const; - long long selectConferenceInfoOrganizerId(long long conferenceInfoId) const; + long long selectConferenceInfoParticipantId(long long conferenceInfoId, + long long participantSipAddressId, + bool isOrganizer) const; long long selectConferenceCallId(const std::string &callId); void deleteContents(long long chatMessageId); @@ -124,8 +133,6 @@ private: std::shared_ptr<EventLog> selectConferenceEvent(const ConferenceId &conferenceId, EventLog::Type type, const soci::row &row) const; - std::shared_ptr<EventLog> selectConferenceCallEvent(const soci::row &row) const; - std::shared_ptr<EventLog> selectConferenceChatMessageEvent(const std::shared_ptr<AbstractChatRoom> &chatRoom, EventLog::Type type, const soci::row &row) const; diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index e5b3f58888..417d960272 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -71,7 +71,7 @@ LINPHONE_BEGIN_NAMESPACE #ifdef HAVE_DB_STORAGE namespace { -constexpr unsigned int ModuleVersionEvents = makeVersion(1, 0, 23); +constexpr unsigned int ModuleVersionEvents = makeVersion(1, 0, 24); constexpr unsigned int ModuleVersionFriends = makeVersion(1, 0, 0); constexpr unsigned int ModuleVersionLegacyFriendsImport = makeVersion(1, 0, 0); constexpr unsigned int ModuleVersionLegacyHistoryImport = makeVersion(1, 0, 0); @@ -637,20 +637,20 @@ long long MainDbPrivate::insertConferenceInfo(const std::shared_ptr<ConferenceIn conferenceInfo->getOrganizer()->getAllParameters()); const auto &participantList = conferenceInfo->getParticipants(); - for (const auto &participantAddress : participantList) { - insertOrUpdateConferenceInfoParticipant(conferenceInfoId, insertSipAddress(participantAddress->getAddress()), - false, participantAddress->getAllParameters()); + for (const auto &participantInfo : participantList) { + insertOrUpdateConferenceInfoParticipant(conferenceInfoId, insertSipAddress(participantInfo->getAddress()), + false, participantInfo->getAllParameters(), false); } - for (const auto &oldParticipantAddress : dbParticipantList) { + for (const auto &oldParticipantInfo : dbParticipantList) { const bool deleted = - (std::find_if(participantList.cbegin(), participantList.cend(), [&oldParticipantAddress](const auto &p) { - return (p->getAddress()->weakEqual(*oldParticipantAddress->getAddress())); + (std::find_if(participantList.cbegin(), participantList.cend(), [&oldParticipantInfo](const auto &p) { + return (p->getAddress()->weakEqual(*oldParticipantInfo->getAddress())); }) == participantList.cend()); if (deleted) { insertOrUpdateConferenceInfoParticipant(conferenceInfoId, - insertSipAddress(oldParticipantAddress->getAddress()), true, - oldParticipantAddress->getAllParameters()); + insertSipAddress(oldParticipantInfo->getAddress()), true, + oldParticipantInfo->getAllParameters(), false); } } @@ -662,59 +662,73 @@ long long MainDbPrivate::insertConferenceInfo(const std::shared_ptr<ConferenceIn #endif } -long long MainDbPrivate::insertOrUpdateConferenceInfoOrganizer(long long conferenceInfoId, - long long organizerSipAddressId, - const ParticipantInfo::participant_params_t params) { +void MainDbPrivate::insertOrUpdateConferenceInfoParticipantParams(long long conferenceInfoParticipantId, + const ParticipantInfo::participant_params_t params) { #ifdef HAVE_DB_STORAGE - long long conferenceInfoOrganizerId = selectConferenceInfoOrganizerId(conferenceInfoId); - auto paramsStr = ParticipantInfo::memberParametersToString(params); - if (conferenceInfoOrganizerId >= 0) { - *dbSession.getBackendSession() << "UPDATE conference_info_organizer SET" - " organizer_sip_address_id = :organizerSipAddressId, params = :paramsStr" - " WHERE conference_info_id = :conferenceInfoId", - soci::use(organizerSipAddressId), soci::use(paramsStr), soci::use(conferenceInfoId); - - return conferenceInfoOrganizerId; + soci::session *session = dbSession.getBackendSession(); + ParticipantInfo::participant_params_t paramsCopy = params; + + static const string organizerParamsQuery = + "SELECT id, key FROM conference_info_participant_params WHERE conference_info_participant_id = :participantId "; + soci::rowset<soci::row> organizerParamsRows = + (session->prepare << organizerParamsQuery, soci::use(conferenceInfoParticipantId)); + + // Update existing keys + for (const auto &organizerParamsRow : organizerParamsRows) { + const long long &id = dbSession.resolveId(organizerParamsRow, 0); + const auto key = organizerParamsRow.get<string>(1); + if (auto el = paramsCopy.find(key); el != paramsCopy.end()) { + *session << "UPDATE conference_info_participant_params SET value = :value WHERE id = :id", + soci::use(el->second), soci::use(id); + paramsCopy.erase(el); + } else { + *session << "DELETE FROM conference_info_participant_params WHERE id = :id", soci::use(id); + } } - *dbSession.getBackendSession() - << "INSERT INTO conference_info_organizer (conference_info_id, organizer_sip_address_id, params)" - " VALUES (:conferenceInfoId, :organizerSipAddressId, :paramsStr)", - soci::use(conferenceInfoId), soci::use(organizerSipAddressId), soci::use(paramsStr); - - return dbSession.getLastInsertId(); -#else - return -1; + // Add new key values pairs + for (const auto &[key, value] : paramsCopy) { + *session << "INSERT INTO conference_info_participant_params (conference_info_participant_id, key, value) " + "VALUES ( :participantId, :key, :value)", + soci::use(conferenceInfoParticipantId), soci::use(key), soci::use(value); + } #endif } +long long MainDbPrivate::insertOrUpdateConferenceInfoOrganizer(long long conferenceInfoId, + long long organizerSipAddressId, + const ParticipantInfo::participant_params_t params) { + return insertOrUpdateConferenceInfoParticipant(conferenceInfoId, organizerSipAddressId, false, params, true); +} + long long MainDbPrivate::insertOrUpdateConferenceInfoParticipant(long long conferenceInfoId, long long participantSipAddressId, bool deleted, - const ParticipantInfo::participant_params_t params) { + const ParticipantInfo::participant_params_t params, + bool isOrganizer) { #ifdef HAVE_DB_STORAGE long long conferenceInfoParticipantId = - selectConferenceInfoParticipantId(conferenceInfoId, participantSipAddressId); + selectConferenceInfoParticipantId(conferenceInfoId, participantSipAddressId, isOrganizer); auto paramsStr = ParticipantInfo::memberParametersToString(params); int participantDeleted = deleted ? 1 : 0; + int isOrganizerInt = isOrganizer ? 1 : 0; if (conferenceInfoParticipantId >= 0) { - *dbSession.getBackendSession() << "UPDATE conference_info_participant SET" - " deleted = :deleted, params = :paramsStr" - " WHERE conference_info_id = :conferenceInfoId AND " - "participant_sip_address_id = :participantSipAddressId", - soci::use(participantDeleted), soci::use(paramsStr), soci::use(conferenceInfoId), - soci::use(participantSipAddressId); + *dbSession.getBackendSession() << "UPDATE conference_info_participant SET deleted = :deleted WHERE id = :id", + soci::use(participantDeleted), soci::use(conferenceInfoParticipantId); + } else { + *dbSession.getBackendSession() + << "INSERT INTO conference_info_participant (conference_info_id, participant_sip_address_id, deleted, " + "is_organizer)" + " VALUES (:conferenceInfoId, :participantSipAddressId, :deleted, :isOrganizer)", + soci::use(conferenceInfoId), soci::use(participantSipAddressId), soci::use(participantDeleted), + soci::use(isOrganizerInt); - return conferenceInfoParticipantId; + conferenceInfoParticipantId = dbSession.getLastInsertId(); } - *dbSession.getBackendSession() - << "INSERT INTO conference_info_participant (conference_info_id, participant_sip_address_id, deleted, params)" - " VALUES (:conferenceInfoId, :participantSipAddressId, :deleted, :paramsStr)", - soci::use(conferenceInfoId), soci::use(participantSipAddressId), soci::use(participantDeleted), - soci::use(paramsStr); + insertOrUpdateConferenceInfoParticipantParams(conferenceInfoParticipantId, params); - return dbSession.getLastInsertId(); + return conferenceInfoParticipantId; #else return -1; #endif @@ -920,28 +934,16 @@ long long MainDbPrivate::selectConferenceInfoId(long long uriSipAddressId) { #endif } -long long MainDbPrivate::selectConferenceInfoOrganizerId(long long conferenceInfoId) const { -#ifdef HAVE_DB_STORAGE - long long conferenceInfoOrganizerId; - - soci::session *session = dbSession.getBackendSession(); - *session << Statements::get(Statements::SelectConferenceInfoOrganizerId), soci::use(conferenceInfoId), - soci::into(conferenceInfoOrganizerId); - - return session->got_data() ? conferenceInfoOrganizerId : -1; -#else - return -1; -#endif -} - long long MainDbPrivate::selectConferenceInfoParticipantId(long long conferenceInfoId, - long long participantSipAddressId) const { + long long participantSipAddressId, + bool isOrganizer) const { #ifdef HAVE_DB_STORAGE long long conferenceInfoParticipantId; + int isOrganizerInt = isOrganizer ? 1 : 0; soci::session *session = dbSession.getBackendSession(); *session << Statements::get(Statements::SelectConferenceInfoParticipantId), soci::use(conferenceInfoId), - soci::use(participantSipAddressId), soci::into(conferenceInfoParticipantId); + soci::use(participantSipAddressId), soci::use(isOrganizerInt), soci::into(conferenceInfoParticipantId); return session->got_data() ? conferenceInfoParticipantId : -1; #else @@ -1080,110 +1082,6 @@ shared_ptr<EventLog> MainDbPrivate::selectConferenceEvent(const ConferenceId &co return make_shared<ConferenceEvent>(type, getConferenceEventCreationTimeFromRow(row), conferenceId); } -shared_ptr<EventLog> MainDbPrivate::selectConferenceCallEvent(const soci::row &row) const { - L_Q(); - - long long eventId = dbSession.resolveId(row, 0); - shared_ptr<EventLog> eventLog = getEventFromCache(eventId); - if (eventLog) return eventLog; - - EventLog::Type type = EventLog::Type(row.get<int>(1)); - - long long conferenceCallId = dbSession.resolveId(row, 3); - auto callLog = getCallLogFromCache(conferenceCallId); - if (callLog == nullptr) { - const std::shared_ptr<Address> from = Address::create(row.get<string>(4)); - const std::shared_ptr<Address> to = Address::create(row.get<string>(5)); - callLog = CallLog::create(q->getCore(), static_cast<LinphoneCallDir>(row.get<int>(6)), from, to); - callLog->setDuration(row.get<int>(7)); - callLog->setStartTime(dbSession.getTime(row, 8)); - callLog->setConnectedTime(dbSession.getTime(row, 9)); - callLog->setStatus(static_cast<LinphoneCallStatus>(row.get<int>(10))); - callLog->setVideoEnabled(!!row.get<int>(11)); - callLog->setQuality((float)row.get<double>(12)); - - soci::indicator ind = row.get_indicator(13); - if (ind == soci::i_ok) callLog->setCallId(row.get<string>(13)); - - ind = row.get_indicator(14); - if (ind == soci::i_ok) callLog->setRefKey(row.get<string>(14)); - - cache(callLog, conferenceCallId); - } - - std::shared_ptr<ConferenceInfo> conferenceInfo = nullptr; - if (row.get_indicator(15) != soci::i_null) { - long long conferenceInfoId = dbSession.resolveId(row, 15); - callLog->setConferenceInfoId(conferenceInfoId); - - auto conferenceInfo = getConferenceInfoFromCache(conferenceInfoId); - if (conferenceInfo == nullptr) { - conferenceInfo = ConferenceInfo::create(); - - std::shared_ptr<Address> uri = Address::create(row.get<string>(17)); - conferenceInfo->setUri(uri); - - conferenceInfo->setDateTime(dbSession.getTime(row, 18)); - conferenceInfo->setDuration(dbSession.getUnsignedInt(row, 19, 0)); - conferenceInfo->setUtf8Subject(row.get<string>(20)); - conferenceInfo->setUtf8Description(row.get<string>(21)); - - unsigned int icsSequence = dbSession.getUnsignedInt(row, 22, 0); - conferenceInfo->setIcsSequence(icsSequence); - conferenceInfo->setIcsUid(row.get<string>(23)); - conferenceInfo->setSecurityLevel( - static_cast<ConferenceParams::SecurityLevel>(dbSession.getUnsignedInt(row, 24, 0))); - - static const string participantsQuery = - "SELECT sip_address.value" - " FROM sip_address, conference_info, conference_info_participant" - " WHERE conference_info.id = :conferenceInfoId" - " AND sip_address.id = conference_info_participant.participant_sip_address_id" - " AND conference_info_participant.conference_info_id = conference_info.id"; - - soci::session *session = dbSession.getBackendSession(); - soci::rowset<soci::row> participantRows = - (session->prepare << participantsQuery, soci::use(conferenceInfoId)); - for (const auto &participantRow : participantRows) { - std::shared_ptr<Address> participant = Address::create(participantRow.get<string>(0)); - auto participantInfo = ParticipantInfo::create(participant); - conferenceInfo->addParticipant(participantInfo); - } - - // For backward compability purposes, get the organizer from conference_info table and set the sequence - // number to that of the conference info stored in the db It may be overridden if the conference organizer - // has been stored in table conference_info_organizer. - std::shared_ptr<Address> organizerAddress = Address::create(row.get<string>(16)); - ParticipantInfo::participant_params_t organizerParams; - organizerParams.insert(std::make_pair(ParticipantInfo::sequenceParameter, std::to_string(icsSequence))); - static const string organizerQuery = - "SELECT sip_address.value, conference_info_organizer.params" - " FROM sip_address, conference_info, conference_info_organizer" - " WHERE conference_info.id = :conferenceInfoId" - " AND sip_address.id = conference_info_organizer.organizer_sip_address_id" - " AND conference_info_organizer.conference_info_id = conference_info.id"; - - soci::rowset<soci::row> organizerRows = (session->prepare << organizerQuery, soci::use(conferenceInfoId)); - for (const auto &organizerRow : organizerRows) { - organizerAddress = Address::create(organizerRow.get<string>(0)); - const string organizerParamsStr = organizerRow.get<string>(1); - organizerParams = ParticipantInfo::stringToMemberParameters(organizerParamsStr); - } - auto organizerInfo = ParticipantInfo::create(organizerAddress); - organizerInfo->setParameters(organizerParams); - conferenceInfo->setOrganizer(organizerInfo); - - cache(conferenceInfo, conferenceInfoId); - } - } - - eventLog = make_shared<ConferenceCallEvent>(type, dbSession.getTime(row, 2), callLog, conferenceInfo); - - cache(eventLog, eventId); - - return eventLog; -} - shared_ptr<EventLog> MainDbPrivate::selectConferenceChatMessageEvent(const shared_ptr<AbstractChatRoom> &chatRoom, BCTBX_UNUSED(EventLog::Type type), const soci::row &row) const { @@ -1919,6 +1817,50 @@ std::shared_ptr<CallLog> MainDbPrivate::selectCallLog(const soci::row &row) cons // Conference Info API. // --------------------------------------------------------------------------- +ParticipantInfo::participant_params_t +MainDbPrivate::selectConferenceInfoParticipantParams(BCTBX_UNUSED(const long long participantId)) const { + ParticipantInfo::participant_params_t participantParams; +#ifdef HAVE_DB_STORAGE + soci::session *session = dbSession.getBackendSession(); + static const string participantParamsQuery = "SELECT key, value FROM conference_info_participant_params WHERE " + "conference_info_participant_id = :participantId"; + soci::rowset<soci::row> participantParamsRows = + (session->prepare << participantParamsQuery, soci::use(participantId)); + for (const auto &participantParamsRow : participantParamsRows) { + const auto key = participantParamsRow.get<string>(0); + const auto value = participantParamsRow.get<string>(1); + participantParams.insert(std::make_pair(key, value)); + } +#endif // HAVE_DB_STORAGE + return participantParams; +} + +ParticipantInfo::participant_params_t MainDbPrivate::migrateConferenceInfoParticipantParams( + BCTBX_UNUSED(const ParticipantInfo::participant_params_t &unprocessedParticipantParams), + BCTBX_UNUSED(const long long participantId)) const { + ParticipantInfo::participant_params_t participantParams; +#ifdef HAVE_DB_STORAGE + soci::session *session = dbSession.getBackendSession(); + // Migrate participant parameters to the new table + for (const auto &[key, value] : unprocessedParticipantParams) { + std::string actualValue = value; + // To keep the backward compatibility, switch role from Unknown to Speaker during the migration + if (key.compare(ParticipantInfo::roleParameter) == 0) { + const auto roleEnum = Participant::textToRole(value); + if (roleEnum == Participant::Role::Unknown) { + actualValue = Participant::roleToText(Participant::Role::Speaker); + } + } + participantParams.insert(std::make_pair(key, actualValue)); + + *session << "INSERT INTO conference_info_participant_params (conference_info_participant_id, key, value) " + "VALUES ( :participantId, :key, :value )", + soci::use(participantId), soci::use(key), soci::use(actualValue); + } +#endif // HAVE_DB_STORAGE + return participantParams; +} + #ifdef HAVE_DB_STORAGE shared_ptr<ConferenceInfo> MainDbPrivate::selectConferenceInfo(const soci::row &row) const { const long long &dbConferenceInfoId = dbSession.resolveId(row, 0); @@ -1951,29 +1893,66 @@ shared_ptr<ConferenceInfo> MainDbPrivate::selectConferenceInfo(const soci::row & std::shared_ptr<Address> organizerAddress = Address::create(row.get<string>(1)); ParticipantInfo::participant_params_t organizerParams; organizerParams.insert(std::make_pair(ParticipantInfo::sequenceParameter, std::to_string(icsSequence))); - static const string organizerQuery = "SELECT sip_address.value, conference_info_organizer.params" - " FROM sip_address, conference_info, conference_info_organizer" - " WHERE conference_info.id = :conferenceInfoId" - " AND sip_address.id = conference_info_organizer.organizer_sip_address_id" - " AND conference_info_organizer.conference_info_id = conference_info.id"; + static const string organizerQuery = + "SELECT sip_address.id, sip_address.value, conference_info_organizer.params, conference_info_organizer.id" + " FROM sip_address, conference_info, conference_info_organizer" + " WHERE conference_info.id = :conferenceInfoId" + " AND sip_address.id = conference_info_organizer.organizer_sip_address_id" + " AND conference_info_organizer.conference_info_id = conference_info.id"; soci::session *session = dbSession.getBackendSession(); soci::rowset<soci::row> organizerRows = (session->prepare << organizerQuery, soci::use(dbConferenceInfoId)); - for (const auto &organizerRow : organizerRows) { - organizerAddress = Address::create(organizerRow.get<string>(0)); - const string organizerParamsStr = organizerRow.get<string>(1); - organizerParams = ParticipantInfo::stringToMemberParameters(organizerParamsStr); + const auto &organizerRowIt = organizerRows.begin(); + if (organizerRowIt != organizerRows.end()) { + const auto &organizerRow = (*organizerRowIt); + const long long &organizerSipAddressId = dbSession.resolveId(organizerRow, 0); + organizerAddress = Address::create(organizerRow.get<string>(1)); + const string organizerParamsStr = organizerRow.get<string>(2); + const long long &organizerId = dbSession.resolveId(organizerRow, 3); + *session << "INSERT INTO conference_info_participant (conference_info_id, participant_sip_address_id, deleted, " + "is_organizer) VALUES (:conferenceInfoId, :participantSipAddressId, :deleted, :isOrganizer)", + soci::use(dbConferenceInfoId), soci::use(organizerSipAddressId), soci::use(0), soci::use(1); + + const long long organizerIdInParticipantTable = dbSession.getLastInsertId(); + const auto unprocessedOrganizerParams = ParticipantInfo::stringToMemberParameters(organizerParamsStr); + organizerParams = + migrateConferenceInfoParticipantParams(unprocessedOrganizerParams, organizerIdInParticipantTable); + + // Delete entry from conference info organizer + *session << "DELETE FROM conference_info_organizer WHERE id = :organizerId", soci::use(organizerId); + } else { + static const string organizerInParticipantTableQuery = + "SELECT sip_address.value, conference_info_participant.id" + " FROM sip_address, conference_info, conference_info_participant" + " WHERE conference_info.id = :conferenceInfoId" + " AND sip_address.id = conference_info_participant.participant_sip_address_id" + " AND conference_info_participant.conference_info_id = conference_info.id AND " + "conference_info_participant.is_organizer = 1"; + + soci::rowset<soci::row> organizerInParticipantTableRows = + (session->prepare << organizerInParticipantTableQuery, soci::use(dbConferenceInfoId)); + const auto &organizerInParticipantTableRowIt = organizerInParticipantTableRows.begin(); + if (organizerInParticipantTableRowIt != organizerInParticipantTableRows.end()) { + const auto &organizerInParticipantTableRow = (*organizerInParticipantTableRowIt); + organizerAddress = Address::create(organizerInParticipantTableRow.get<string>(0)); + + const long long &organizerId = dbSession.resolveId(organizerInParticipantTableRow, 1); + organizerParams = selectConferenceInfoParticipantParams(organizerId); + } } + auto organizerInfo = ParticipantInfo::create(organizerAddress); organizerInfo->setParameters(organizerParams); conferenceInfo->setOrganizer(organizerInfo); static const string participantQuery = - "SELECT sip_address.value, conference_info_participant.deleted, conference_info_participant.params" + "SELECT sip_address.value, conference_info_participant.deleted, conference_info_participant.params, " + "conference_info_participant.id" " FROM sip_address, conference_info, conference_info_participant" " WHERE conference_info.id = :conferenceInfoId" " AND sip_address.id = conference_info_participant.participant_sip_address_id" - " AND conference_info_participant.conference_info_id = conference_info.id"; + " AND conference_info_participant.conference_info_id = conference_info.id AND " + "conference_info_participant.is_organizer = 0"; soci::rowset<soci::row> participantRows = (session->prepare << participantQuery, soci::use(dbConferenceInfoId)); for (const auto &participantRow : participantRows) { @@ -1981,9 +1960,20 @@ shared_ptr<ConferenceInfo> MainDbPrivate::selectConferenceInfo(const soci::row & if (deleted == 0) { std::shared_ptr<Address> participantAddress = Address::create(participantRow.get<string>(0)); const string participantParamsStr = participantRow.get<string>(2); - ParticipantInfo::participant_params_t participantParams = - ParticipantInfo::stringToMemberParameters(participantParamsStr); + const long long &participantId = dbSession.resolveId(participantRow, 3); + ParticipantInfo::participant_params_t participantParams; auto participantInfo = ParticipantInfo::create(participantAddress); + if (participantParamsStr.empty()) { + participantParams = selectConferenceInfoParticipantParams(participantId); + } else { + const auto unprocessedParticipantParams = + ParticipantInfo::stringToMemberParameters(participantParamsStr); + participantParams = migrateConferenceInfoParticipantParams(unprocessedParticipantParams, participantId); + // Set parameter string to an empty string + *session << "UPDATE conference_info_participant SET params = :paramsStr WHERE conference_info_id = " + ":conferenceInfoId", + soci::use(std::string()), soci::use(dbConferenceInfoId); + } participantInfo->setParameters(participantParams); conferenceInfo->addParticipant(participantInfo); } @@ -2413,6 +2403,40 @@ void MainDbPrivate::updateSchema() { *session << "ALTER TABLE chat_room ADD COLUMN muted BOOLEAN NOT NULL DEFAULT 0"; } + if (version < makeVersion(1, 0, 24)) { + *session << "ALTER TABLE conference_info_participant ADD COLUMN is_organizer BOOLEAN NOT NULL DEFAULT 0"; + // We must recreate table conference_info_participant to change the UNIQUE constraint. + *session << "CREATE TABLE conference_info_participant_clone AS SELECT * FROM conference_info_participant"; + *session << "DROP TABLE conference_info_participant"; + + *session << "CREATE TABLE IF NOT EXISTS conference_info_participant (" + " id" + + dbSession.primaryKeyStr("BIGINT UNSIGNED") + + "," + + " conference_info_id" + + dbSession.primaryKeyRefStr("BIGINT UNSIGNED") + + " NOT NULL," + " participant_sip_address_id" + + dbSession.primaryKeyRefStr("BIGINT UNSIGNED") + + " NOT NULL," + " deleted BOOLEAN NOT NULL DEFAULT 0," + " params VARCHAR(2048) DEFAULT ''," + " is_organizer BOOLEAN NOT NULL DEFAULT 0," + + " UNIQUE (conference_info_id, participant_sip_address_id, is_organizer)," + + " FOREIGN KEY (conference_info_id)" + " REFERENCES conference_info(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + + charset; + *session << "INSERT INTO conference_info_participant SELECT * FROM conference_info_participant_clone"; + } + // /!\ Warning : if varchar columns < 255 were to be indexed, their size must be set back to 191 = max indexable // (KEY or UNIQUE) varchar size for mysql < 5.7 with charset utf8mb4 (both here and in column creation) @@ -3352,6 +3376,24 @@ void MainDb::init() { ") " + charset; + *session << "CREATE TABLE IF NOT EXISTS conference_info_participant_params (" + " id" + + primaryKeyStr("BIGINT UNSIGNED") + + "," + + " conference_info_participant_id" + + primaryKeyRefStr("BIGINT UNSIGNED") + + " NOT NULL," + " key VARCHAR(2048) DEFAULT ''," + " value VARCHAR(2048) DEFAULT ''," + + " UNIQUE (conference_info_participant_id, key)," + " FOREIGN KEY (conference_info_participant_id)" + " REFERENCES conference_info_participant(id)" + " ON DELETE CASCADE" + ") " + + charset; + *session << "CREATE TABLE IF NOT EXISTS conference_call (" " id" + primaryKeyStr("BIGINT UNSIGNED") + diff --git a/tester/local_conference_edition_tester.cpp b/tester/local_conference_edition_tester.cpp index 64514173ce..abdbabca03 100644 --- a/tester/local_conference_edition_tester.cpp +++ b/tester/local_conference_edition_tester.cpp @@ -830,7 +830,6 @@ static void edit_simple_conference_base(bool_t from_organizer, } } - ms_message("%s - END mgr %s", __func__, linphone_core_get_identity(mgr->lc)); bool is_focus = (mgr == focus.getCMgr()); bctbx_list_t *participants_info2 = bctbx_list_copy_with_data( participants_info, (bctbx_list_copy_func)linphone_participant_info_clone); @@ -915,6 +914,7 @@ static void edit_simple_conference_base(bool_t from_organizer, } add = !add; } + bctbx_list_free(initialInfos); bctbx_list_free_with_data(participants_info, (bctbx_list_free_func)linphone_participant_info_unref); ms_free(uid); ms_free(conference_address_str); -- GitLab