Commit 5a9d0dfd authored by Ronan's avatar Ronan
Browse files

feat(BasicToClientGroupChatRoom): capabilities contains Migrate if the proxy is a basic chatroom

parent 67053e8e
......@@ -92,7 +92,10 @@ BasicToClientGroupChatRoom::BasicToClientGroupChatRoom (const shared_ptr<ChatRoo
BasicToClientGroupChatRoom::CapabilitiesMask BasicToClientGroupChatRoom::getCapabilities () const {
L_D();
return d->chatRoom->getCapabilities() | BasicToClientGroupChatRoom::Capabilities::Migratable;
CapabilitiesMask capabilities = d->chatRoom->getCapabilities();
if (capabilities.isSet(Capabilities::Basic))
capabilities.set(Capabilities::Migratable);
return capabilities;
}
shared_ptr<ChatMessage> BasicToClientGroupChatRoom::createChatMessage () {
......
......@@ -65,66 +65,66 @@ MainDb::MainDb (const shared_ptr<Core> &core) : AbstractDb(*new MainDbPrivate),
// Soci backend.
// -----------------------------------------------------------------------------
template<typename T>
struct EnumToSql {
T first;
const char *second;
};
template<typename T>
static constexpr const char *mapEnumToSql (const EnumToSql<T> enumToSql[], size_t n, T key) {
return n == 0 ? "" : (
enumToSql[n - 1].first == key ? enumToSql[n - 1].second : mapEnumToSql(enumToSql, n - 1, key)
);
}
template<typename T>
struct EnumToSql {
T first;
const char *second;
};
template<typename T>
static constexpr const char *mapEnumToSql (const EnumToSql<T> enumToSql[], size_t n, T key) {
return n == 0 ? "" : (
enumToSql[n - 1].first == key ? enumToSql[n - 1].second : mapEnumToSql(enumToSql, n - 1, key)
);
}
static constexpr EnumToSql<MainDb::Filter> eventFilterToSql[] = {
{ MainDb::ConferenceCallFilter, "3, 4" },
{ MainDb::ConferenceChatMessageFilter, "5" },
{ MainDb::ConferenceInfoFilter, "1, 2, 6, 7, 8, 9, 10, 11, 12" }
};
static constexpr EnumToSql<MainDb::Filter> eventFilterToSql[] = {
{ MainDb::ConferenceCallFilter, "3, 4" },
{ MainDb::ConferenceChatMessageFilter, "5" },
{ MainDb::ConferenceInfoFilter, "1, 2, 6, 7, 8, 9, 10, 11, 12" }
};
static constexpr const char *mapEventFilterToSql (MainDb::Filter filter) {
return mapEnumToSql(
eventFilterToSql, sizeof eventFilterToSql / sizeof eventFilterToSql[0], filter
);
}
static constexpr const char *mapEventFilterToSql (MainDb::Filter filter) {
return mapEnumToSql(
eventFilterToSql, sizeof eventFilterToSql / sizeof eventFilterToSql[0], filter
);
}
// -----------------------------------------------------------------------------
static string buildSqlEventFilter (
const list<MainDb::Filter> &filters,
MainDb::FilterMask mask,
const string &condKeyWord = "WHERE"
) {
L_ASSERT(
find_if(filters.cbegin(), filters.cend(), [](const MainDb::Filter &filter) {
return filter == MainDb::NoFilter;
}) == filters.cend()
);
if (mask == MainDb::NoFilter)
return "";
bool isStart = true;
string sql;
for (const auto &filter : filters) {
if (!mask.isSet(filter))
continue;
if (isStart) {
isStart = false;
sql += " " + condKeyWord + " type IN (";
} else
sql += ", ";
sql += mapEventFilterToSql(filter);
}
if (!isStart)
sql += ") ";
return sql;
}
static string buildSqlEventFilter (
const list<MainDb::Filter> &filters,
MainDb::FilterMask mask,
const string &condKeyWord = "WHERE"
) {
L_ASSERT(
find_if(filters.cbegin(), filters.cend(), [](const MainDb::Filter &filter) {
return filter == MainDb::NoFilter;
}) == filters.cend()
);
if (mask == MainDb::NoFilter)
return "";
bool isStart = true;
string sql;
for (const auto &filter : filters) {
if (!mask.isSet(filter))
continue;
if (isStart) {
isStart = false;
sql += " " + condKeyWord + " type IN (";
} else
sql += ", ";
sql += mapEventFilterToSql(filter);
}
if (!isStart)
sql += ") ";
return sql;
}
// -----------------------------------------------------------------------------
......@@ -148,2421 +148,2426 @@ static constexpr string &blobToString (string &in) {
// -----------------------------------------------------------------------------
long long MainDbPrivate::resolveId (const soci::row &row, int col) const {
L_Q();
// See: http://soci.sourceforge.net/doc/master/backends/
// `row id` is not supported by soci on Sqlite3. It's necessary to cast id to int...
return q->getBackend() == AbstractDb::Sqlite3
? static_cast<long long>(row.get<int>(0))
: static_cast<long long>(row.get<unsigned long long>(0));
}
long long MainDbPrivate::resolveId (const soci::row &row, int col) const {
L_Q();
// See: http://soci.sourceforge.net/doc/master/backends/
// `row id` is not supported by soci on Sqlite3. It's necessary to cast id to int...
return q->getBackend() == AbstractDb::Sqlite3
? static_cast<long long>(row.get<int>(0))
: static_cast<long long>(row.get<unsigned long long>(0));
}
// -----------------------------------------------------------------------------
long long MainDbPrivate::insertSipAddress (const string &sipAddress) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
long long MainDbPrivate::insertSipAddress (const string &sipAddress) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
long long id = selectSipAddressId(sipAddress);
if (id >= 0)
return id;
long long id = selectSipAddressId(sipAddress);
if (id >= 0)
return id;
lInfo() << "Insert new sip address in database: `" << sipAddress << "`.";
*session << "INSERT INTO sip_address (value) VALUES (:sipAddress)", soci::use(sipAddress);
return q->getLastInsertId();
}
lInfo() << "Insert new sip address in database: `" << sipAddress << "`.";
*session << "INSERT INTO sip_address (value) VALUES (:sipAddress)", soci::use(sipAddress);
return q->getLastInsertId();
}
void MainDbPrivate::insertContent (long long eventId, const Content &content) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
void MainDbPrivate::insertContent (long long eventId, const Content &content) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
const long long &contentTypeId = insertContentType(content.getContentType().asString());
const string &body = content.getBodyAsString();
*session << "INSERT INTO chat_message_content (event_id, content_type_id, body) VALUES"
" (:eventId, :contentTypeId, :body)", soci::use(eventId), soci::use(contentTypeId),
soci::use(body);
const long long &chatMessageContentId = q->getLastInsertId();
if (content.getContentType().isFile()) {
const FileContent &fileContent = static_cast<const FileContent &>(content);
const string &name = fileContent.getFileName();
const size_t &size = fileContent.getFileSize();
const string &path = fileContent.getFilePath();
*session << "INSERT INTO chat_message_file_content (chat_message_content_id, name, size, path) VALUES "
" (:chatMessageContentId, :name, :size, :path)",
soci::use(chatMessageContentId), soci::use(name), soci::use(size), soci::use(path);
}
for (const auto &appData : content.getAppDataMap())
*session << "INSERT INTO chat_message_content_app_data (chat_message_content_id, name, data) VALUES"
" (:chatMessageContentId, :name, :data)",
soci::use(chatMessageContentId), soci::use(appData.first), soci::use(appData.second);
}
const long long &contentTypeId = insertContentType(content.getContentType().asString());
const string &body = content.getBodyAsString();
*session << "INSERT INTO chat_message_content (event_id, content_type_id, body) VALUES"
" (:eventId, :contentTypeId, :body)", soci::use(eventId), soci::use(contentTypeId),
soci::use(body);
const long long &chatMessageContentId = q->getLastInsertId();
if (content.getContentType().isFile()) {
const FileContent &fileContent = static_cast<const FileContent &>(content);
const string &name = fileContent.getFileName();
const size_t &size = fileContent.getFileSize();
const string &path = fileContent.getFilePath();
*session << "INSERT INTO chat_message_file_content (chat_message_content_id, name, size, path) VALUES "
" (:chatMessageContentId, :name, :size, :path)",
soci::use(chatMessageContentId), soci::use(name), soci::use(size), soci::use(path);
}
long long MainDbPrivate::insertContentType (const string &contentType) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
for (const auto &appData : content.getAppDataMap())
*session << "INSERT INTO chat_message_content_app_data (chat_message_content_id, name, data) VALUES"
" (:chatMessageContentId, :name, :data)",
soci::use(chatMessageContentId), soci::use(appData.first), soci::use(appData.second);
}
long long id;
*session << "SELECT id FROM content_type WHERE value = :contentType", soci::use(contentType), soci::into(id);
if (session->got_data())
return id;
long long MainDbPrivate::insertContentType (const string &contentType) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
lInfo() << "Insert new content type in database: `" << contentType << "`.";
*session << "INSERT INTO content_type (value) VALUES (:contentType)", soci::use(contentType);
return q->getLastInsertId();
}
long long MainDbPrivate::insertOrUpdateImportedBasicChatRoom (
long long peerSipAddressId,
long long localSipAddressId,
const tm &creationTime
) {
L_Q();
long long id;
*session << "SELECT id FROM content_type WHERE value = :contentType", soci::use(contentType), soci::into(id);
if (session->got_data())
return id;
soci::session *session = dbSession.getBackendSession<soci::session>();
lInfo() << "Insert new content type in database: `" << contentType << "`.";
*session << "INSERT INTO content_type (value) VALUES (:contentType)", soci::use(contentType);
return q->getLastInsertId();
long long id = selectChatRoomId(peerSipAddressId, localSipAddressId);
if (id >= 0) {
*session << "UPDATE chat_room SET last_update_time = :lastUpdateTime WHERE id = :id",
soci::use(creationTime), soci::use(id);
return id;
}
long long MainDbPrivate::insertOrUpdateImportedBasicChatRoom (
long long peerSipAddressId,
long long localSipAddressId,
const tm &creationTime
) {
L_Q();
static const int capabilities = ChatRoom::CapabilitiesMask(
{ ChatRoom::Capabilities::Basic, ChatRoom::Capabilities::Migratable }
);
lInfo() << "Insert new chat room in database: (peer=" << peerSipAddressId <<
", local=" << localSipAddressId << ", capabilities=" << capabilities << ").";
*session << "INSERT INTO chat_room ("
" peer_sip_address_id, local_sip_address_id, creation_time, last_update_time, capabilities"
") VALUES (:peerSipAddressId, :localSipAddressId, :creationTime, :lastUpdateTime, :capabilities)",
soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime), soci::use(creationTime),
soci::use(capabilities);
soci::session *session = dbSession.getBackendSession<soci::session>();
return q->getLastInsertId();
}
long long id = selectChatRoomId(peerSipAddressId, localSipAddressId);
if (id >= 0) {
*session << "UPDATE chat_room SET last_update_time = :lastUpdateTime WHERE id = :id",
soci::use(creationTime), soci::use(id);
return id;
}
long long MainDbPrivate::insertChatRoom (const shared_ptr<AbstractChatRoom> &chatRoom) {
L_Q();
static const int capabilities = ChatRoom::CapabilitiesMask(
{ ChatRoom::Capabilities::Basic, ChatRoom::Capabilities::Migratable }
);
lInfo() << "Insert new chat room in database: (peer=" << peerSipAddressId <<
", local=" << localSipAddressId << ", capabilities=" << capabilities << ").";
*session << "INSERT INTO chat_room ("
" peer_sip_address_id, local_sip_address_id, creation_time, last_update_time, capabilities"
") VALUES (:peerSipAddressId, :localSipAddressId, :creationTime, :lastUpdateTime, :capabilities)",
soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime), soci::use(creationTime),
soci::use(capabilities);
return q->getLastInsertId();
}
soci::session *session = dbSession.getBackendSession<soci::session>();
long long MainDbPrivate::insertChatRoom (const shared_ptr<AbstractChatRoom> &chatRoom) {
L_Q();
const ChatRoomId &chatRoomId = chatRoom->getChatRoomId();
const long long &peerSipAddressId = insertSipAddress(chatRoomId.getPeerAddress().asString());
const long long &localSipAddressId = insertSipAddress(chatRoomId.getLocalAddress().asString());
soci::session *session = dbSession.getBackendSession<soci::session>();
long long id = selectChatRoomId(peerSipAddressId, localSipAddressId);
if (id >= 0) {
lError() << "Unable to insert chat room (it already exists): (peer=" << peerSipAddressId <<
", local=" << localSipAddressId << ").";
return id;
}
const ChatRoomId &chatRoomId = chatRoom->getChatRoomId();
const long long &peerSipAddressId = insertSipAddress(chatRoomId.getPeerAddress().asString());
const long long &localSipAddressId = insertSipAddress(chatRoomId.getLocalAddress().asString());
lInfo() << "Insert new chat room in database: (peer=" << peerSipAddressId <<
", local=" << localSipAddressId << ").";
long long id = selectChatRoomId(peerSipAddressId, localSipAddressId);
if (id >= 0) {
lError() << "Unable to insert chat room (it already exists): (peer=" << peerSipAddressId <<
", local=" << localSipAddressId << ").";
return id;
}
const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime());
// Remove capabilities like `Proxy`.
const int &capabilities = chatRoom->getCapabilities() & ChatRoom::CapabilitiesMask({
ChatRoom::Capabilities::Basic, ChatRoom::Capabilities::RealTimeText,
ChatRoom::Capabilities::Conference, ChatRoom::Capabilities::Migratable
});
lInfo() << "Insert new chat room in database: (peer=" << peerSipAddressId <<
", local=" << localSipAddressId << ").";
const string &subject = chatRoom->getSubject();
const int &flags = chatRoom->hasBeenLeft();
*session << "INSERT INTO chat_room ("
" peer_sip_address_id, local_sip_address_id, creation_time, last_update_time, capabilities, subject, flags"
") VALUES (:peerSipAddressId, :localSipAddressId, :creationTime, :lastUpdateTime, :capabilities, :subject, :flags)",
soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime), soci::use(creationTime),
soci::use(capabilities), soci::use(subject), soci::use(flags);
const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime());
const int &capabilities = chatRoom->getCapabilities();
const string &subject = chatRoom->getSubject();
const int &flags = chatRoom->hasBeenLeft();
*session << "INSERT INTO chat_room ("
" peer_sip_address_id, local_sip_address_id, creation_time, last_update_time, capabilities, subject, flags"
") VALUES (:peerSipAddressId, :localSipAddressId, :creationTime, :lastUpdateTime, :capabilities, :subject, :flags)",
soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime), soci::use(creationTime),
soci::use(capabilities), soci::use(subject), soci::use(flags);
id = q->getLastInsertId();
if (!chatRoom->canHandleParticipants())
return id;
// Do not add 'me' when creating a server-group-chat-room.
if (chatRoomId.getLocalAddress() != chatRoomId.getPeerAddress()) {
shared_ptr<Participant> me = chatRoom->getMe();
long long meId = insertChatRoomParticipant(
id,
insertSipAddress(me->getAddress().asString()),
me->isAdmin()
);
for (const auto &device : me->getPrivate()->getDevices())
insertChatRoomParticipantDevice(meId, insertSipAddress(device->getAddress().asString()));
}
id = q->getLastInsertId();
if (!chatRoom->canHandleParticipants())
return id;
for (const auto &participant : chatRoom->getParticipants()) {
long long participantId = insertChatRoomParticipant(
id,
insertSipAddress(participant->getAddress().asString()),
participant->isAdmin()
);
for (const auto &device : participant->getPrivate()->getDevices())
insertChatRoomParticipantDevice(participantId, insertSipAddress(device->getAddress().asString()));
}
// Do not add 'me' when creating a server-group-chat-room.
if (chatRoomId.getLocalAddress() != chatRoomId.getPeerAddress()) {
shared_ptr<Participant> me = chatRoom->getMe();
long long meId = insertChatRoomParticipant(
id,
insertSipAddress(me->getAddress().asString()),
me->isAdmin()
);
for (const auto &device : me->getPrivate()->getDevices())
insertChatRoomParticipantDevice(meId, insertSipAddress(device->getAddress().asString()));
}
return id;
for (const auto &participant : chatRoom->getParticipants()) {
long long participantId = insertChatRoomParticipant(
id,
insertSipAddress(participant->getAddress().asString()),
participant->isAdmin()
);
for (const auto &device : participant->getPrivate()->getDevices())
insertChatRoomParticipantDevice(participantId, insertSipAddress(device->getAddress().asString()));
}
long long MainDbPrivate::insertChatRoomParticipant (
long long chatRoomId,
long long participantSipAddressId,
bool isAdmin
) {
L_Q();
return id;
}
soci::session *session = dbSession.getBackendSession<soci::session>();
long long id = selectChatRoomParticipantId(chatRoomId, participantSipAddressId);
if (id >= 0) {
// See: https://stackoverflow.com/a/15299655 (cast to reference)
*session << "UPDATE chat_room_participant SET is_admin = :isAdmin WHERE id = :id",
soci::use(static_cast<const int &>(isAdmin)), soci::use(id);
return id;
}
long long MainDbPrivate::insertChatRoomParticipant (
long long chatRoomId,
long long participantSipAddressId,
bool isAdmin
) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
long long id = selectChatRoomParticipantId(chatRoomId, participantSipAddressId);
if (id >= 0) {
// See: https://stackoverflow.com/a/15299655 (cast to reference)
*session << "UPDATE chat_room_participant SET is_admin = :isAdmin WHERE id = :id",
soci::use(static_cast<const int &>(isAdmin)), soci::use(id);
return id;
}
lInfo() << "Insert new chat room participant in database: `" << participantSipAddressId <<
"` (isAdmin=" << isAdmin << ").";
*session << "INSERT INTO chat_room_participant (chat_room_id, participant_sip_address_id, is_admin)"
" VALUES (:chatRoomId, :participantSipAddressId, :isAdmin)",
soci::use(chatRoomId), soci::use(participantSipAddressId), soci::use(static_cast<const int &>(isAdmin));
lInfo() << "Insert new chat room participant in database: `" << participantSipAddressId <<
"` (isAdmin=" << isAdmin << ").";
*session << "INSERT INTO chat_room_participant (chat_room_id, participant_sip_address_id, is_admin)"
" VALUES (:chatRoomId, :participantSipAddressId, :isAdmin)",
soci::use(chatRoomId), soci::use(participantSipAddressId), soci::use(static_cast<const int &>(isAdmin));
return q->getLastInsertId();
}
return q->getLastInsertId();
}
void MainDbPrivate::insertChatRoomParticipantDevice (
long long participantId,
long long participantDeviceSipAddressId
) {
soci::session *session = dbSession.getBackendSession<soci::session>();
long long count;
*session << "SELECT COUNT(*) FROM chat_room_participant_device"
" WHERE chat_room_participant_id = :participantId"
" AND participant_device_sip_address_id = :participantDeviceSipAddressId",
soci::into(count), soci::use(participantId), soci::use(participantDeviceSipAddressId);
if (count)
return;
lInfo() << "Insert new chat room participant device in database: `" << participantDeviceSipAddressId << "`.";
*session << "INSERT INTO chat_room_participant_device (chat_room_participant_id, participant_device_sip_address_id)"
" VALUES (:participantId, :participantDeviceSipAddressId)",
soci::use(participantId), soci::use(participantDeviceSipAddressId);
}
void MainDbPrivate::insertChatRoomParticipantDevice (
long long participantId,
long long participantDeviceSipAddressId
) {
soci::session *session = dbSession.getBackendSession<soci::session>();
long long count;
*session << "SELECT COUNT(*) FROM chat_room_participant_device"
" WHERE chat_room_participant_id = :participantId"
" AND participant_device_sip_address_id = :participantDeviceSipAddressId",
soci::into(count), soci::use(participantId), soci::use(participantDeviceSipAddressId);
if (count)
return;
lInfo() << "Insert new chat room participant device in database: `" << participantDeviceSipAddressId << "`.";
*session << "INSERT INTO chat_room_participant_device (chat_room_participant_id, participant_device_sip_address_id)"
" VALUES (:participantId, :participantDeviceSipAddressId)",
soci::use(participantId), soci::use(participantDeviceSipAddressId);
}
void MainDbPrivate::insertChatMessageParticipant (long long eventId, long long sipAddressId, int state) {
// TODO: Deal with read messages.
// Remove if displayed? Think a good alorithm for mark as read.
soci::session *session = dbSession.getBackendSession<soci::session>();
soci::statement statement = (
session->prepare << "UPDATE chat_message_participant SET state = :state"
" WHERE event_id = :eventId AND participant_sip_address_id = :sipAddressId",
soci::use(state), soci::use(eventId), soci::use(sipAddressId)
);
statement.execute();
if (statement.get_affected_rows() == 0 && state != static_cast<int>(ChatMessage::State::Displayed))
*session << "INSERT INTO chat_message_participant (event_id, participant_sip_address_id, state)"
" VALUES (:eventId, :sipAddressId, :state)",
soci::use(eventId), soci::use(sipAddressId), soci::use(state);
}
void MainDbPrivate::insertChatMessageParticipant (long long eventId, long long sipAddressId, int state) {
// TODO: Deal with read messages.
// Remove if displayed? Think a good alorithm for mark as read.
soci::session *session = dbSession.getBackendSession<soci::session>();
soci::statement statement = (
session->prepare << "UPDATE chat_message_participant SET state = :state"
" WHERE event_id = :eventId AND participant_sip_address_id = :sipAddressId",
soci::use(state), soci::use(eventId), soci::use(sipAddressId)
);
statement.execute();
if (statement.get_affected_rows() == 0 && state != static_cast<int>(ChatMessage::State::Displayed))
*session << "INSERT INTO chat_message_participant (event_id, participant_sip_address_id, state)"
" VALUES (:eventId, :sipAddressId, :state)",
soci::use(eventId), soci::use(sipAddressId), soci::use(state);
}
// -----------------------------------------------------------------------------
long long MainDbPrivate::selectSipAddressId (const string &sipAddress) const {
soci::session *session = dbSession.getBackendSession<soci::session>();
long long MainDbPrivate::selectSipAddressId (const string &sipAddress) const {
soci::session *session = dbSession.getBackendSession<soci::session>();
long long id;
*session << "SELECT id FROM sip_address WHERE value = :sipAddress", soci::use(sipAddress), soci::into(id);
return session->got_data() ? id : -1;
}
long long id;
*session << "SELECT id FROM sip_address WHERE value = :sipAddress", soci::use(sipAddress), soci::into(id);
return session->got_data() ? id : -1;
}
long long MainDbPrivate::selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const {
soci::session *session = dbSession.getBackendSession<soci::session>();
long long MainDbPrivate::selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const {
soci::session *session = dbSession.getBackendSession<soci::session>();
long long id;
*session << "SELECT id FROM chat_room"
" WHERE peer_sip_address_id = :peerSipAddressId AND local_sip_address_id = :localSipAddressId",
soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::into(id);
return session->got_data() ? id : -1;
}
long long id;
*session << "SELECT id FROM chat_room"
" WHERE peer_sip_address_id = :peerSipAddressId AND local_sip_address_id = :localSipAddressId",
soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::into(id);
return session->got_data() ? id : -1;
}
long long MainDbPrivate::selectChatRoomId (const ChatRoomId &chatRoomId) const {
long long peerSipAddressId = selectSipAddressId(chatRoomId.getPeerAddress().asString());
if (peerSipAddressId < 0)
return -1;
long long MainDbPrivate::selectChatRoomId (const ChatRoomId &chatRoomId) const {
long long peerSipAddressId = selectSipAddressId(chatRoomId.getPeerAddress().asString());
if (peerSipAddressId < 0)
return -1;
long long localSipAddressId = selectSipAddressId(chatRoomId.getLocalAddress().asString());
if (localSipAddressId < 0)
return -1;
long long localSipAddressId = selectSipAddressId(chatRoomId.getLocalAddress().asString());
if (localSipAddressId < 0)
return -1;
return selectChatRoomId(peerSipAddressId, localSipAddressId);
}
return selectChatRoomId(peerSipAddressId, localSipAddressId);
}
long long MainDbPrivate::selectChatRoomParticipantId (long long chatRoomId, long long participantSipAddressId) const {
long long id;