Skip to content

Commit b399f91

Browse files
committed
exmdb: rework get_mbox_perm queries (1/2)
get_mbox_perm performs not great in the face of many ACEs: * SELECT … LEFT JOIN … LEFT JOIN: 62096 µs * mlist membership test: 3586543 µs * [5950X system with 100k ACEs] Rewrite the LEFT JOIN as two separate queries. The sections now complete in * SELECTs: 1432 µs * mlist: 360306 µs References: DESK-3893, DESK-3984
1 parent f7c4f6d commit b399f91

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

exch/exmdb/store.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <gromox/database.h>
1313
#include <gromox/exmdb_common_util.hpp>
1414
#include <gromox/exmdb_server.hpp>
15+
#include <gromox/flat_set.hpp>
1516
#include <gromox/list_file.hpp>
1617
#include <gromox/mapidefs.h>
1718
#include <gromox/mysql_adaptor.hpp>
@@ -231,18 +232,16 @@ BOOL exmdb_server::get_mbox_perm(const char *dir,
231232
*ppermission = rightsNone;
232233

233234
/* Store permission := union of folder permissions */
235+
gromox::maybe_flat_set<uint64_t> seen_fid;
234236
auto pstmt = gx_sql_prep(pdb->psqlite,
235-
"SELECT p1.folder_id, p2.permission, p3.permission "
236-
"FROM permissions AS p1 LEFT JOIN permissions AS p2 "
237-
"ON p1.folder_id=p2.folder_id AND p2.username=? "
238-
"LEFT JOIN permissions AS p3 "
239-
"ON p1.folder_id=p3.folder_id AND p3.username='default'");
237+
"SELECT folder_id, permission FROM permissions WHERE username=?");
240238
if (pstmt == nullptr)
241239
return FALSE;
242240
sqlite3_bind_text(pstmt, 1, username, -1, SQLITE_STATIC);
243241
while (pstmt.step() == SQLITE_ROW) {
244242
auto fid = pstmt.col_uint64(0);
245-
auto perm = pstmt.col_uint64(sqlite3_column_type(pstmt, 1) != SQLITE_NULL ? 1 : 2);
243+
auto perm = pstmt.col_uint64(1);
244+
seen_fid.emplace(fid);
246245
*ppermission |= perm;
247246
/*
248247
* Outlook and g-web only expose IPM_SUBTREE and below, so permissions
@@ -262,6 +261,17 @@ BOOL exmdb_server::get_mbox_perm(const char *dir,
262261
if (fid == PRIVATE_FID_IPMSUBTREE && perm & frightsOwner)
263262
*ppermission |= frightsGromoxStoreOwner;
264263
}
264+
pstmt.reset();
265+
pstmt.bind_text(1, "default");
266+
while (pstmt.step() == SQLITE_ROW) {
267+
auto fid = pstmt.col_uint64(0);
268+
if (seen_fid.find(fid) != seen_fid.end())
269+
continue;
270+
auto perm = pstmt.col_uint64(1);
271+
*ppermission |= perm;
272+
if (fid == PRIVATE_FID_IPMSUBTREE && perm & frightsOwner)
273+
*ppermission |= frightsGromoxStoreOwner;
274+
}
265275
pstmt.finalize();
266276

267277
/* add in mlist permissions(?) */

lib/dbop_sqlite.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,17 @@ static constexpr char tbl_perms_0[] =
113113
"CREATE INDEX fid_permissions_index ON permissions(folder_id);"
114114
"CREATE UNIQUE INDEX folder_username_index ON permissions(folder_id, username);";
115115

116+
static constexpr char tbl_perms_24[] =
117+
"CREATE TABLE permissions ("
118+
" member_id INTEGER PRIMARY KEY AUTOINCREMENT,"
119+
" folder_id INTEGER NOT NULL,"
120+
" username TEXT COLLATE NOCASE NOT NULL,"
121+
" permission INTEGER NOT NULL,"
122+
" FOREIGN KEY (folder_id) REFERENCES folders (folder_id) ON DELETE CASCADE ON UPDATE CASCADE);"
123+
"CREATE INDEX fid_permissions_index ON permissions(folder_id);"
124+
"CREATE UNIQUE INDEX folder_username_index ON permissions(folder_id, username);"
125+
"CREATE UNIQUE INDEX folder_username_index2 ON permissions(username, folder_id);";
126+
116127
static constexpr char tbl_rules_0[] =
117128
"CREATE TABLE rules ("
118129
" rule_id INTEGER PRIMARY KEY AUTOINCREMENT,"
@@ -372,6 +383,9 @@ tbl_addmsgtimeindex_23[] =
372383
"LEFT JOIN message_properties AS rt ON m.message_id=rt.message_id AND rt.proptag=0xe060040 " /* PR_MESSAGE_DELIVERY_TIME */
373384
"LEFT JOIN message_properties AS st ON m.message_id=st.message_id AND st.proptag=0x390040 " /* PR_CLIENT_SUBMIT_TIME */
374385
"WHERE m.parent_fid IS NOT NULL AND m.is_associated=0 AND m.is_deleted=0";
386+
static constexpr char tbl_mboxpermissionindex_24[] =
387+
/* this helps determining mbox perm (bitwise-OR of all folders) */
388+
"CREATE UNIQUE INDEX folder_username_index2 ON permissions(username, folder_id);";
375389

376390
static constexpr char tbl_pub_folders_0[] =
377391
"CREATE TABLE folders ("
@@ -451,7 +465,7 @@ static constexpr tbl_init tbl_pvt_init_top[] = {
451465
{"named_properties", tbl_namedprops_12},
452466
{"store_properties", tbl_storeprops_2},
453467
{"folder_properties", tbl_fldprops_3},
454-
{"permissions", tbl_perms_0},
468+
{"permissions", tbl_perms_24},
455469
{"rules", tbl_rules_0},
456470
{"message_properties", tbl_msgprops_4},
457471
{"message_changes", tbl_msgchgs_0},
@@ -498,7 +512,7 @@ static constexpr tbl_init tbl_pub_init_top[] = {
498512
{"named_properties", tbl_namedprops_0},
499513
{"store_properties", tbl_storeprops_2},
500514
{"folder_properties", tbl_fldprops_3},
501-
{"permissions", tbl_perms_0},
515+
{"permissions", tbl_perms_24},
502516
{"rules", tbl_rules_0},
503517
{"message_properties", tbl_msgprops_4},
504518
{"message_changes", tbl_msgchgs_0},
@@ -640,6 +654,7 @@ static constexpr tblite_upgradefn tbl_pvt_upgrade_list[] = {
640654
{21, tbl_mtimeindex_21},
641655
{22, tbl_msgtimeindex_22},
642656
{23, tbl_addmsgtimeindex_23},
657+
{24, tbl_mboxpermissionindex_24},
643658
/* advance schema numbers in lockstep with public stores */
644659
TABLE_END,
645660
};
@@ -660,6 +675,7 @@ static constexpr tblite_upgradefn tbl_pub_upgrade_list[] = {
660675
{21, tbl_mtimeindex_21},
661676
{22, tbl_msgtimeindex_22},
662677
{23, tbl_addmsgtimeindex_23},
678+
{24, tbl_mboxpermissionindex_24},
663679
/* advance schema numbers in lockstep with private stores */
664680
TABLE_END,
665681
};

0 commit comments

Comments
 (0)