{"action":"created","comment":{"url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/comments/55359307","id":55359307,"diff_hunk":"@@ -91,22 +163,50 @@ public Uri addNewNote(long mid, long did, String[] fields, String tags) {\n      * @return whether there already exists a card with the same model ID and content in the first field\n      */\n     public boolean checkForDuplicates(long mid, long did, String[] fields) {\n-        // TODO: investigate performance optimization using csum if necessary\n+        Long noteId = findNoteId(mid, did, fields);\n+        return noteId != null;\n+    }\n+\n+    /**\n+     * Get corresponding noteId\n+     *\n+     * @param mid model id\n+     * @param did deck id\n+     * @param fields list of fields\n+     * @return first existing noteId or null if the note does not yet exist\n+     */\n+    public Long findNoteId(long mid, long did, String[] fields) {","path":"api/src/main/java/com/ichi2/anki/api/AddContentApi.java","position":118,"original_position":123,"commit_id":"e569bba72d2cff48cdd2ff2f3d75b3aaa0fd0ff3","original_commit_id":"e4e508bd7b8477d7a65f08bd4a543ce8ed370753","user":{"login":"timrae","id":2818274,"avatar_url":"https://avatars.githubusercontent.com/u/2818274?v=3","gravatar_id":"","url":"https://api.github.com/users/timrae","html_url":"https://github.com/timrae","followers_url":"https://api.github.com/users/timrae/followers","following_url":"https://api.github.com/users/timrae/following{/other_user}","gists_url":"https://api.github.com/users/timrae/gists{/gist_id}","starred_url":"https://api.github.com/users/timrae/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/timrae/subscriptions","organizations_url":"https://api.github.com/users/timrae/orgs","repos_url":"https://api.github.com/users/timrae/repos","events_url":"https://api.github.com/users/timrae/events{/privacy}","received_events_url":"https://api.github.com/users/timrae/received_events","type":"User","site_admin":false},"body":"Maybe just cut and paste the code into a text editor for now and paste it into the new branch after pulling from develop","created_at":"2016-03-08T13:41:45Z","updated_at":"2016-03-08T13:41:45Z","html_url":"https://github.com/ankidroid/Anki-Android/pull/4110#discussion_r55359307","pull_request_url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110","_links":{"self":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/comments/55359307"},"html":{"href":"https://github.com/ankidroid/Anki-Android/pull/4110#discussion_r55359307"},"pull_request":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110"}}},"pull_request":{"url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110","id":61350532,"html_url":"https://github.com/ankidroid/Anki-Android/pull/4110","diff_url":"https://github.com/ankidroid/Anki-Android/pull/4110.diff","patch_url":"https://github.com/ankidroid/Anki-Android/pull/4110.patch","issue_url":"https://api.github.com/repos/ankidroid/Anki-Android/issues/4110","number":4110,"state":"open","locked":false,"title":"Added support for bulk insert of Notes: 2000% faster","user":{"login":"marcardar","id":409640,"avatar_url":"https://avatars.githubusercontent.com/u/409640?v=3","gravatar_id":"","url":"https://api.github.com/users/marcardar","html_url":"https://github.com/marcardar","followers_url":"https://api.github.com/users/marcardar/followers","following_url":"https://api.github.com/users/marcardar/following{/other_user}","gists_url":"https://api.github.com/users/marcardar/gists{/gist_id}","starred_url":"https://api.github.com/users/marcardar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcardar/subscriptions","organizations_url":"https://api.github.com/users/marcardar/orgs","repos_url":"https://api.github.com/users/marcardar/repos","events_url":"https://api.github.com/users/marcardar/events{/privacy}","received_events_url":"https://api.github.com/users/marcardar/received_events","type":"User","site_admin":false},"body":"This is a major performance improvement for inserting large numbers (hundreds or thousands) of Notes.\r\n\r\nAdded support for bulkInsert() to the content provider as well as the API (addNewNotes). This will work with existing provider but new provider implementation is much faster.\r\n\r\nAdded support for inserting a new note into a deck with one provider call (instead of three in existing API implementation) to the provider's insert() method. Again, this will work with existing provider, but new provider implementation is about 39% faster.\r\n\r\nAdded API support for updating an existing note: updateNote() and updateNoteTags(). (This is already supported by existing provider).\r\n\r\nAdded API support for counting number of notes (with a certain model id) in a deck: countNotes(). I couldn't see a way to count notes in a deck while ignoring model id. (This is already supported by existing provider).\r\n\r\nAdded provider support for \"count(*)\" column in projection.\r\n\r\nAdded a meta-data key to the provider (in manifest) so that the API can query whether the provider supports these new features.\r\n\r\nHere are the stats from my testing on a Nexus 6P (6.0.1):\r\n\r\nInsert 2122 notes (same model (three fields), same deck, single card)\r\n\r\nAnkidroid v.20600116 (3 provider calls per note): **191secs**\r\nRewrote as single provider call per note: 138secs\r\nRewrote as single provider call in total (bulk insert): 119secs\r\n\r\nThis PR: single provider call in total (bulk insert, single transaction):\r\nIgnore duplicates (empty deck): 44secs\r\nIgnore duplicates (deck already contains 2122 notes, so none added): 34secs\r\nNo duplicate check (empty deck): **8.5secs**","created_at":"2016-03-02T04:43:31Z","updated_at":"2016-03-08T13:41:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f277d4a3a647a32555abdf1d7a9055998271df62","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110/commits","review_comments_url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110/comments","review_comment_url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ankidroid/Anki-Android/issues/4110/comments","statuses_url":"https://api.github.com/repos/ankidroid/Anki-Android/statuses/e569bba72d2cff48cdd2ff2f3d75b3aaa0fd0ff3","head":{"label":"marcardar:notes-bulk-insert","ref":"notes-bulk-insert","sha":"e569bba72d2cff48cdd2ff2f3d75b3aaa0fd0ff3","user":{"login":"marcardar","id":409640,"avatar_url":"https://avatars.githubusercontent.com/u/409640?v=3","gravatar_id":"","url":"https://api.github.com/users/marcardar","html_url":"https://github.com/marcardar","followers_url":"https://api.github.com/users/marcardar/followers","following_url":"https://api.github.com/users/marcardar/following{/other_user}","gists_url":"https://api.github.com/users/marcardar/gists{/gist_id}","starred_url":"https://api.github.com/users/marcardar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcardar/subscriptions","organizations_url":"https://api.github.com/users/marcardar/orgs","repos_url":"https://api.github.com/users/marcardar/repos","events_url":"https://api.github.com/users/marcardar/events{/privacy}","received_events_url":"https://api.github.com/users/marcardar/received_events","type":"User","site_admin":false},"repo":{"id":52933751,"name":"Anki-Android","full_name":"marcardar/Anki-Android","owner":{"login":"marcardar","id":409640,"avatar_url":"https://avatars.githubusercontent.com/u/409640?v=3","gravatar_id":"","url":"https://api.github.com/users/marcardar","html_url":"https://github.com/marcardar","followers_url":"https://api.github.com/users/marcardar/followers","following_url":"https://api.github.com/users/marcardar/following{/other_user}","gists_url":"https://api.github.com/users/marcardar/gists{/gist_id}","starred_url":"https://api.github.com/users/marcardar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcardar/subscriptions","organizations_url":"https://api.github.com/users/marcardar/orgs","repos_url":"https://api.github.com/users/marcardar/repos","events_url":"https://api.github.com/users/marcardar/events{/privacy}","received_events_url":"https://api.github.com/users/marcardar/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/marcardar/Anki-Android","description":"AnkiDroid: Anki on Android","fork":true,"url":"https://api.github.com/repos/marcardar/Anki-Android","forks_url":"https://api.github.com/repos/marcardar/Anki-Android/forks","keys_url":"https://api.github.com/repos/marcardar/Anki-Android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/marcardar/Anki-Android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/marcardar/Anki-Android/teams","hooks_url":"https://api.github.com/repos/marcardar/Anki-Android/hooks","issue_events_url":"https://api.github.com/repos/marcardar/Anki-Android/issues/events{/number}","events_url":"https://api.github.com/repos/marcardar/Anki-Android/events","assignees_url":"https://api.github.com/repos/marcardar/Anki-Android/assignees{/user}","branches_url":"https://api.github.com/repos/marcardar/Anki-Android/branches{/branch}","tags_url":"https://api.github.com/repos/marcardar/Anki-Android/tags","blobs_url":"https://api.github.com/repos/marcardar/Anki-Android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/marcardar/Anki-Android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/marcardar/Anki-Android/git/refs{/sha}","trees_url":"https://api.github.com/repos/marcardar/Anki-Android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/marcardar/Anki-Android/statuses/{sha}","languages_url":"https://api.github.com/repos/marcardar/Anki-Android/languages","stargazers_url":"https://api.github.com/repos/marcardar/Anki-Android/stargazers","contributors_url":"https://api.github.com/repos/marcardar/Anki-Android/contributors","subscribers_url":"https://api.github.com/repos/marcardar/Anki-Android/subscribers","subscription_url":"https://api.github.com/repos/marcardar/Anki-Android/subscription","commits_url":"https://api.github.com/repos/marcardar/Anki-Android/commits{/sha}","git_commits_url":"https://api.github.com/repos/marcardar/Anki-Android/git/commits{/sha}","comments_url":"https://api.github.com/repos/marcardar/Anki-Android/comments{/number}","issue_comment_url":"https://api.github.com/repos/marcardar/Anki-Android/issues/comments{/number}","contents_url":"https://api.github.com/repos/marcardar/Anki-Android/contents/{+path}","compare_url":"https://api.github.com/repos/marcardar/Anki-Android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/marcardar/Anki-Android/merges","archive_url":"https://api.github.com/repos/marcardar/Anki-Android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/marcardar/Anki-Android/downloads","issues_url":"https://api.github.com/repos/marcardar/Anki-Android/issues{/number}","pulls_url":"https://api.github.com/repos/marcardar/Anki-Android/pulls{/number}","milestones_url":"https://api.github.com/repos/marcardar/Anki-Android/milestones{/number}","notifications_url":"https://api.github.com/repos/marcardar/Anki-Android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/marcardar/Anki-Android/labels{/name}","releases_url":"https://api.github.com/repos/marcardar/Anki-Android/releases{/id}","deployments_url":"https://api.github.com/repos/marcardar/Anki-Android/deployments","created_at":"2016-03-02T04:26:22Z","updated_at":"2016-03-02T04:26:27Z","pushed_at":"2016-03-08T13:34:48Z","git_url":"git://github.com/marcardar/Anki-Android.git","ssh_url":"git@github.com:marcardar/Anki-Android.git","clone_url":"https://github.com/marcardar/Anki-Android.git","svn_url":"https://github.com/marcardar/Anki-Android","homepage":"","size":102385,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"ankidroid:develop","ref":"develop","sha":"6d0a687fd84d8b3af6ad4b2e1a7001e4e7f5e882","user":{"login":"ankidroid","id":3320903,"avatar_url":"https://avatars.githubusercontent.com/u/3320903?v=3","gravatar_id":"","url":"https://api.github.com/users/ankidroid","html_url":"https://github.com/ankidroid","followers_url":"https://api.github.com/users/ankidroid/followers","following_url":"https://api.github.com/users/ankidroid/following{/other_user}","gists_url":"https://api.github.com/users/ankidroid/gists{/gist_id}","starred_url":"https://api.github.com/users/ankidroid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ankidroid/subscriptions","organizations_url":"https://api.github.com/users/ankidroid/orgs","repos_url":"https://api.github.com/users/ankidroid/repos","events_url":"https://api.github.com/users/ankidroid/events{/privacy}","received_events_url":"https://api.github.com/users/ankidroid/received_events","type":"Organization","site_admin":false},"repo":{"id":7716883,"name":"Anki-Android","full_name":"ankidroid/Anki-Android","owner":{"login":"ankidroid","id":3320903,"avatar_url":"https://avatars.githubusercontent.com/u/3320903?v=3","gravatar_id":"","url":"https://api.github.com/users/ankidroid","html_url":"https://github.com/ankidroid","followers_url":"https://api.github.com/users/ankidroid/followers","following_url":"https://api.github.com/users/ankidroid/following{/other_user}","gists_url":"https://api.github.com/users/ankidroid/gists{/gist_id}","starred_url":"https://api.github.com/users/ankidroid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ankidroid/subscriptions","organizations_url":"https://api.github.com/users/ankidroid/orgs","repos_url":"https://api.github.com/users/ankidroid/repos","events_url":"https://api.github.com/users/ankidroid/events{/privacy}","received_events_url":"https://api.github.com/users/ankidroid/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ankidroid/Anki-Android","description":"AnkiDroid: Anki on Android","fork":false,"url":"https://api.github.com/repos/ankidroid/Anki-Android","forks_url":"https://api.github.com/repos/ankidroid/Anki-Android/forks","keys_url":"https://api.github.com/repos/ankidroid/Anki-Android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ankidroid/Anki-Android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ankidroid/Anki-Android/teams","hooks_url":"https://api.github.com/repos/ankidroid/Anki-Android/hooks","issue_events_url":"https://api.github.com/repos/ankidroid/Anki-Android/issues/events{/number}","events_url":"https://api.github.com/repos/ankidroid/Anki-Android/events","assignees_url":"https://api.github.com/repos/ankidroid/Anki-Android/assignees{/user}","branches_url":"https://api.github.com/repos/ankidroid/Anki-Android/branches{/branch}","tags_url":"https://api.github.com/repos/ankidroid/Anki-Android/tags","blobs_url":"https://api.github.com/repos/ankidroid/Anki-Android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ankidroid/Anki-Android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ankidroid/Anki-Android/git/refs{/sha}","trees_url":"https://api.github.com/repos/ankidroid/Anki-Android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ankidroid/Anki-Android/statuses/{sha}","languages_url":"https://api.github.com/repos/ankidroid/Anki-Android/languages","stargazers_url":"https://api.github.com/repos/ankidroid/Anki-Android/stargazers","contributors_url":"https://api.github.com/repos/ankidroid/Anki-Android/contributors","subscribers_url":"https://api.github.com/repos/ankidroid/Anki-Android/subscribers","subscription_url":"https://api.github.com/repos/ankidroid/Anki-Android/subscription","commits_url":"https://api.github.com/repos/ankidroid/Anki-Android/commits{/sha}","git_commits_url":"https://api.github.com/repos/ankidroid/Anki-Android/git/commits{/sha}","comments_url":"https://api.github.com/repos/ankidroid/Anki-Android/comments{/number}","issue_comment_url":"https://api.github.com/repos/ankidroid/Anki-Android/issues/comments{/number}","contents_url":"https://api.github.com/repos/ankidroid/Anki-Android/contents/{+path}","compare_url":"https://api.github.com/repos/ankidroid/Anki-Android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ankidroid/Anki-Android/merges","archive_url":"https://api.github.com/repos/ankidroid/Anki-Android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ankidroid/Anki-Android/downloads","issues_url":"https://api.github.com/repos/ankidroid/Anki-Android/issues{/number}","pulls_url":"https://api.github.com/repos/ankidroid/Anki-Android/pulls{/number}","milestones_url":"https://api.github.com/repos/ankidroid/Anki-Android/milestones{/number}","notifications_url":"https://api.github.com/repos/ankidroid/Anki-Android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ankidroid/Anki-Android/labels{/name}","releases_url":"https://api.github.com/repos/ankidroid/Anki-Android/releases{/id}","deployments_url":"https://api.github.com/repos/ankidroid/Anki-Android/deployments","created_at":"2013-01-20T13:55:53Z","updated_at":"2016-03-08T06:21:38Z","pushed_at":"2016-03-08T13:34:48Z","git_url":"git://github.com/ankidroid/Anki-Android.git","ssh_url":"git@github.com:ankidroid/Anki-Android.git","clone_url":"https://github.com/ankidroid/Anki-Android.git","svn_url":"https://github.com/ankidroid/Anki-Android","homepage":"","size":124292,"stargazers_count":503,"watchers_count":503,"language":"Java","has_issues":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":408,"mirror_url":null,"open_issues_count":278,"forks":408,"open_issues":278,"watchers":503,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110"},"html":{"href":"https://github.com/ankidroid/Anki-Android/pull/4110"},"issue":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/issues/4110"},"comments":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/issues/4110/comments"},"review_comments":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110/comments"},"review_comment":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/pulls/4110/commits"},"statuses":{"href":"https://api.github.com/repos/ankidroid/Anki-Android/statuses/e569bba72d2cff48cdd2ff2f3d75b3aaa0fd0ff3"}}}}