Commit Graph

24719 Commits

Author SHA1 Message Date
Nora Trapp
3fdcb8effe Fix crash with early message manager 2021-09-01 16:36:50 -03:00
Matthew Chen
14666cfab0 Merge branch 'charlesmchen/paymentFormatting' into release/5.19.0 2021-09-01 16:31:13 -03:00
Matthew Chen
d3633cc0c7 Refine payments formatting. 2021-09-01 16:30:49 -03:00
Matthew Chen
4a79019e83 Refine payments formatting. 2021-09-01 16:30:49 -03:00
Matthew Chen
30defb4890 Refine payments formatting. 2021-09-01 16:30:49 -03:00
Matthew Chen
6a2edc2b8c Refine payments formatting. 2021-09-01 16:30:49 -03:00
Matthew Chen
49f83b35ec Refine payments formatting. 2021-09-01 16:30:49 -03:00
Matthew Chen
a3bd0338d5 Refine payments formatting. 2021-09-01 16:30:48 -03:00
Matthew Chen
d5e451a422 Merge branch 'charlesmchen/paymentsBetaMoreCountries' into release/5.19.0 2021-09-01 16:30:05 -03:00
Matthew Chen
aacfc16d8a Extend payments beta to more countries. 2021-09-01 11:06:35 -03:00
Matthew Chen
db8da1f1d6 Merge branch 'charlesmchen/avatarReupload' into release/5.19.0 2021-09-01 10:57:22 -03:00
Matthew Chen
59512bbdf2 Fill in missing profile avatars. 2021-09-01 10:46:17 -03:00
Matthew Chen
fedbd6aea8 Update l10n strings. 2021-08-31 10:14:42 -03:00
Matthew Chen
632ca86094 Update release notes. 2021-08-31 10:05:29 -03:00
Matthew Chen
304b0e91fb "Bump build to 5.19.0.5031." (Beta) 2021-08-30 17:46:06 -03:00
Matthew Chen
fffca57867 "Feature flags for .beta." 2021-08-30 17:45:59 -03:00
Matthew Chen
5f35380d83 Update l10n strings. 2021-08-30 17:45:39 -03:00
Matthew Chen
6627945156 Merge branch 'charlesmchen/conversationPickerSearchCrash' into release/5.19.0 2021-08-30 17:10:11 -03:00
Matthew Chen
c680a4b36b Fix crash in conversation picker. 2021-08-30 17:09:50 -03:00
Matthew Chen
e3c8af828e Merge branch 'charlesmchen/minorFixes2021.08.30' into release/5.19.0 2021-08-30 17:06:41 -03:00
Matthew Chen
016e814884 Restore conversation picker selection state after navigation bar changes. 2021-08-30 17:06:27 -03:00
Matthew Chen
82a4dfa955 Ensure conversation picker selection UI reflects theme. 2021-08-30 17:06:27 -03:00
Matthew Chen
2bf974bc58 Don't restore keyboard after CVC message context menu if the menu item presented a VC. 2021-08-30 17:06:27 -03:00
Matthew Chen
c474d3f07c Ensure message actions footer updates for theme changes; fixed styling of its selection label. 2021-08-30 17:06:27 -03:00
Matthew Chen
e6676db82a Revert "Merge remote-tracking branch 'private/mlin/PR/PashtoLanguageSupport' into release/5.19.0"
This reverts commit 5c23dfa341, reversing
changes made to 31cf855901.
2021-08-30 15:24:34 -03:00
Matthew Chen
345c46dba4 Bump CFBundleVersion to 5030. 2021-08-30 09:32:04 -03:00
Matthew Chen
c10e851a32 "Bump build to 5.19.0.56." (Internal) 2021-08-30 09:17:42 -03:00
Matthew Chen
236a4c78fb Update l10n strings. 2021-08-30 09:17:32 -03:00
Matthew Chen
e89f25088c Merge branch 'mlin/PR/BetterLoadQueryIndexing' into release/5.19.0 2021-08-30 08:56:58 -03:00
Michelle Linington
1012d7b42d Tune indices for more performant conversation loads
- Replaces the existing placeholder excluding index for two new indices,
  optimized to reduce disk I/O. These are partial indices, only
  applicable to the placeholder excluding queries performed during
  conversation load. They're also covering indices. Most queries will be
  resolved by only consulting the index. There's no need to consult the
  backing rows in the model_TSInteraction table.
- Adds a helper SQL bytecode explainer for debugging

Tracking down these optimizations took a great deal of time. I promised
in a comment that this commit message will have a thorough explanation
of why these indices are constructed the way they are. The TL;DR:
- There are a bunch of limitations on index column ordering that you
  should be aware of.
- Partial indices can help you avoid some of those limitations
- SQLite can be finnicky when trying to decide if a partial index is
  applicable to a query.
- When an index covers a given query, it can avoid a whole bunch of
  disk I/O.
- Index row size matters, and SQLite may choose a less efficient index
  if it looks like it might be smaller.

The long explanation of lessons learned along the way. All of this is
based on observation, documentation, and trial-and-error:

1. SQLite can be *very* strict when deciding whether or not to use a
   partial index. Compare these two index declarations:
  > CREATE INDEX index1 ON table(uniqueThreadId, id) WHERE 'recordType IS NOT 70';
  > CREATE INDEX index2 ON table(uniqueThreadId, id) WHERE recordType IS NOT 70;

  Note the only difference between the two partial index declarations is
  wrapping the WHERE clause in quotes. The GRDB index builder we were
  using before would do this on our behalf.

  Now let's run this query against both indices. The indices we declared
  *should* be a perfect choice for this query:
  > SELECT COUNT(*) FROM table WHERE uniqueThreadId = 'abc123'
  > AND id > 100 AND recordType IS NOT 70;

  With the first index:
  > `--SEARCH TABLE model_TSInteraction USING INDEX index_interactions_on_threadUniqueId_and_id (uniqueThreadId=? AND id>?)
  With the second index:
  > `--SEARCH TABLE model_TSInteraction USING INDEX index2 (uniqueThreadId=? AND id>?)

  By dropping the quotes around the WHERE clause, SQLite's query planner
  is now convinced that the partial index is applicable to the query
  we're running. This is good, since as SQLite iterates over the index,
  it can skip any recordType comparisons. It also reduces the search
  space, since it doesn't even need to read rows it should exclude.

2. Covering indices can be a huge performance win. An index is covering
   when every column in the index matches some element. Let's again
   compare some indices:
  > CREATE INDEX index1 ON table(uniqueThreadId, id) WHERE recordType IS NOT 70;
  > CREATE INDEX index2 ON table(uniqueThreadId, id, uniqueId) WHERE recordType IS NOT 70;
  > CREATE INDEX index3 ON table(uniqueThreadId, id, recordType, uniqueId) WHERE recordType IS NOT 70;
  (Why a difference between index2 and index3? See the next section)

  When run on this query:
  > SELECT uniqueId FROM table WHERE uniqueThreadId = 'abc123'
  > AND id > 100 AND recordType IS NOT 70;

  The first index:
  > --SEARCH TABLE model_TSInteraction USING INDEX index1 (uniqueThreadId=? AND id>?)
  The second index:
  > --SEARCH TABLE model_TSInteraction USING INDEX index2 (uniqueThreadId=? AND id>?)
  The third index:
  > --SEARCH TABLE model_TSInteraction USING COVERING INDEX index3 (uniqueThreadId=? AND id>?)

  You can see the difference in the actual query bytecode by running:
  "EXPLAIN [query]" (not "EXPLAIN QUERY PLAN"). Notice that when run
  against the first index, it needs to perform two reads. One against
  the table, and another against the index. The only reason it's
  fetching the model is to grab the uniqueId in operation 9.
  > 0     Init           0     12    0                    0   Start at 12
  > 1     OpenRead       0     10    0     67             0   root=10 iDb=0; model_TSInteraction
  > 2     OpenRead       1     162160  0     k(3,,,)        0   root=162160 iDb=0; index1
  > 3     String8        0     1     0     abc123         0   r[1]='abc123'
  > 4     Integer        100   2     0                    0   r[2]=100
  > 5     SeekGT         1     11    1     2              0   key=r[1..2]
  > 6       IdxGT          1     11    1     1              0   key=r[1]
  > 7       DeferredSeek   1     0     0                    0   Move 0 to 1.rowid if needed
  > 8       Column         0     2     3                    0   r[3]=model_TSInteraction.uniqueId
  > 9       ResultRow      3     1     0                    0   output=r[3]
  > 10    Next           1     6     0                    0
  > 11    Halt           0     0     0                    0
  > 12    Transaction    0     0     198   0              1   usesStmtJournal=0
  > 13    Goto           0     1     0                    0

3. SQLite will not consider a partial index covering unless the columns
   defining the index condition are also included in the index content.
   No idea why, but this is why index2 above isn't considered covering
   while index3 is.

4. Index column ordering matters. Briefly, if a WHERE clause in a query
   has any sort of inequality comparisons (everything but IS, IN and =),
   then every subsequent column in an index cannot be used. (mostly)

  For example:
  > CREATE INDEX ON Table(a,b,c);
  > SELECT * WHERE AND b > 100 AND c = "hi";

  Column C isn't going to be usable on the index since we're performing
  an inequality comparison on B. There are loads of exceptions SQLite
  can try to work around this. You can learn more here:
  https://www.sqlite.org/optoverview.html

  How this applies to this change. Consider these two indices:
  > CREATE INDEX index1 ON table(uniqueThreadId, id, recordType, uniqueId) WHERE recordType IS NOT 70;
  > CREATE INDEX index2 ON table(uniqueThreadId, recordType, id, uniqueId) WHERE recordType IS NOT 70;
  > SELECT uniqueId FROM table WHERE uniqueThreadId = 'abc123'
  > AND id > 100 AND recordType IS NOT 70;

  index1 is absolutely going to be the better choice here. Since index1
  is sorted by id first, it's easy for SQLite to binary search to the
  correct offset in the index and then just scan down the index.
  (verifying that each recordType IS NOT 70 along the way, which will
   always hold true because of the partial index condition).

5. Index size matters. At this point, we've constructed this index:
   > CREATE INDEX index1 ON table(uniqueThreadId, id, recordType, uniqueId) WHERE recordType IS NOT 70;

  And SQLite is using it for queries like this. Great!
  > SELECT uniqueId FROM model_TSInteraction
  > WHERE uniqueThreadId = 'whatever' AND recordType IS NOT 70
  > ORDER BY id LIMIT 2 OFFSET 0
  > `--SEARCH TABLE model_TSInteraction USING COVERING INDEX index1 (uniqueThreadId=?)

  Here's a simpler query that we need to run to. It is even less
  specific than the one above so we should expect it to use our
  index.
  > SELECT COUNT(*) FROM model_TSInteraction
  > WHERE uniqueThreadId = 'blah' AND recordType IS NOT 70;
  > `--SEARCH TABLE model_TSInteraction USING COVERING INDEX index_model_TSInteraction_on_uniqueThreadId_and_hasEnded_and_recordType (uniqueThreadId=?)

  As best I can tell, the reason SQLite is picking this existing index
  is because each row in the index is smaller.
  Each row in our index: [String, Int, Int, String]
  Each row in the chosen index: [String, Bool, Int]

  The query planner had to choose, was it better off picking the index
  that's more specific but larger, or less specific but smaller. It
  picked the latter.

  To work around this we can add a *second* index, that's even smaller
  that the index it's choosing.
  > CREATE INDEX index2 ON table(uniqueThreadId, recordType) WHERE recordType IS NOT 70;

  Now the query picks our new index to run the count.
  --SEARCH TABLE model_TSInteraction USING COVERING INDEX index2 (uniqueThreadId=?)
2021-08-30 08:55:53 -03:00
Matthew Chen
5c23dfa341 Merge remote-tracking branch 'private/mlin/PR/PashtoLanguageSupport' into release/5.19.0 2021-08-30 08:29:12 -03:00
Michelle Linington
e383e1459c Add Pashto localization files 2021-08-29 15:36:21 -07:00
Matthew Chen
31cf855901 "Feature flags for .qa." 2021-08-27 22:14:28 -03:00
Matthew Chen
4d146c5a7e "Bump build to 5.19.0.55." (Beta) 2021-08-27 22:14:23 -03:00
Matthew Chen
e2ed0e8a88 "Feature flags for .beta." 2021-08-27 22:14:20 -03:00
Matthew Chen
fa0ef14c0b Merge branch 'charlesmchen/resumeAttachmentUploadCrash' into release/5.19.0 2021-08-27 22:12:38 -03:00
Matthew Chen
8908233e72 Fix 'resume attachment upload' crash. 2021-08-27 22:12:16 -03:00
Matthew Chen
8c56bcfc57 Update l10n strings. 2021-08-27 22:11:30 -03:00
Michelle Linington
13c950bd60 "Bump build to 5.19.0.54." (Internal) 2021-08-27 16:33:32 -07:00
Michelle Linington
671c3db656 Fix inadvertent compilation error 2021-08-27 16:28:53 -07:00
Michelle Linington
d8880306a9 "Bump build to 5.19.0.53." (Internal) 2021-08-27 16:23:24 -07:00
Michelle Linington
6af6272cea Merge branch 'mlin/PR/EnableSenderKey' into release/5.19.0 2021-08-27 16:14:00 -07:00
Michelle Linington
94726b3dad Enable sender key 2021-08-27 16:13:48 -07:00
Michelle Linington
67f15704eb Merge branch 'mlin/PR/SenderKeyFinalFixes' into release/5.19.0 2021-08-27 16:13:13 -07:00
Michelle Linington
aad8af1ef4 Lint 2021-08-27 16:12:24 -07:00
Michelle Linington
94f3d297a4 Fixes a few final sender key issues:
- The excludePlaceholders parameter was inverted, but the DebugFlag
  wasn't
- Fix an issue with how we detect content-less sync messages
2021-08-27 16:12:24 -07:00
Michelle Linington
f617d5d589 Merge branch 'mlin/PR/SmallSenderKeyFixes' into release/5.19.0 2021-08-27 16:10:59 -07:00
Michelle Linington
d3ff346af9 PR Feedback 2021-08-27 16:10:36 -07:00
Michelle Linington
aff4be51d2 Some small sender key changes
- Annotate groupIds fetched from the UD messgae content as untrusted
- Double check the sender of a failed decryption is a member of the
  group before inserting a placeholder/error message
- Double check group membership hasn't changed before deciding not to
  expire a sender key.
2021-08-27 16:10:36 -07:00
Nora Trapp
17dad45ef1 Merge branch 'nt/message-send-perf' into release/5.19.0 2021-08-27 12:58:31 -07:00