package it.niedermann.owncloud.notes.persistence.dao; import androidx.lifecycle.LiveData; import androidx.room.Dao; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.Update; import java.util.List; import java.util.Set; import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper; import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount; import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.NoteIdPair; import it.niedermann.owncloud.notes.shared.model.DBStatus; @SuppressWarnings("JavadocReference") @Dao public interface NoteDao { @Insert long addNote(Note note); @Update(onConflict = OnConflictStrategy.REPLACE) int updateNote(Note newNote); @Query("DELETE FROM NOTE WHERE accountId = :accountId") int deleteByAccountId(Long accountId); String getNoteById = "SELECT * FROM NOTE WHERE id = :id"; String getContent = "SELECT content FROM NOTE WHERE id = :id"; String count = "SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId"; String countFavorites = "SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId AND favorite = 1"; String searchRecentByModified = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, modified DESC"; String searchRecentLexicographically = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, title COLLATE NOCASE ASC"; String searchFavoritesByModified = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY modified DESC"; String searchFavoritesLexicographically = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY title COLLATE NOCASE ASC"; String searchUncategorizedByModified = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, modified DESC"; String searchUncategorizedLexicographically = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, title COLLATE NOCASE ASC"; String searchCategoryByModified = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, modified DESC"; String searchCategoryLexicographically = "SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, title COLLATE NOCASE ASC"; @Query(getNoteById) LiveData getNoteById$(long id); @Query(getNoteById) Note getNoteById(long id); @Query(count) LiveData count$(long accountId); @Query(count) Integer count(long accountId); @Query(countFavorites) LiveData countFavorites$(long accountId); @Query(countFavorites) Integer countFavorites(long accountId); @Query(getContent) LiveData getContent$(Long id); @Query(getContent) String getContent(Long id); @Query(searchRecentByModified) LiveData> searchRecentByModified$(long accountId, String query); @Query(searchRecentByModified) List searchRecentByModified(long accountId, String query); @Query(searchRecentLexicographically) LiveData> searchRecentLexicographically$(long accountId, String query); @Query(searchRecentLexicographically) List searchRecentLexicographically(long accountId, String query); @Query(searchFavoritesByModified) LiveData> searchFavoritesByModified$(long accountId, String query); @Query(searchFavoritesByModified) List searchFavoritesByModified(long accountId, String query); @Query(searchFavoritesLexicographically) LiveData> searchFavoritesLexicographically$(long accountId, String query); @Query(searchFavoritesLexicographically) List searchFavoritesLexicographically(long accountId, String query); @Query(searchUncategorizedByModified) LiveData> searchUncategorizedByModified$(long accountId, String query); @Query(searchUncategorizedByModified) List searchUncategorizedByModified(long accountId, String query); @Query(searchUncategorizedLexicographically) LiveData> searchUncategorizedLexicographically$(long accountId, String query); @Query(searchUncategorizedLexicographically) List searchUncategorizedLexicographically(long accountId, String query); @Query(searchCategoryByModified) LiveData> searchCategoryByModified$(long accountId, String query, String category); @Query(searchCategoryByModified) List searchCategoryByModified(long accountId, String query, String category); @Query(searchCategoryLexicographically) LiveData> searchCategoryLexicographically$(long accountId, String query, String category); @Query(searchCategoryLexicographically) List searchCategoryLexicographically(long accountId, String query, String category); @Query("DELETE FROM NOTE WHERE id = :id AND status = :forceDBStatus") void deleteByNoteId(long id, DBStatus forceDBStatus); @Query("UPDATE NOTE SET scrollY = :scrollY WHERE id = :id") void updateScrollY(long id, int scrollY); @Query("UPDATE NOTE SET status = :status WHERE id = :id") void updateStatus(long id, DBStatus status); @Query("UPDATE NOTE SET category = :category WHERE id = :id") void updateCategory(long id, String category); /** * Gets all the {@link Note#remoteId}s of all not deleted {@link Note}s of an {@link Account} * * @param accountId get the {@link Note#remoteId} from all {@link Note}s of this {@link Account} * @return {@link Set} {@link Note#remoteId}s from all {@link Note}s */ @Query("SELECT DISTINCT remoteId FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED'") List getRemoteIds(long accountId); @Query("SELECT id, remoteId FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED'") List getRemoteIdAndId(long accountId); /** * Get a single {@link Note} by {@link Note#remoteId} (aka. Nextcloud file id) * * @param remoteId int - {@link Note#remoteId} of the requested {@link Note} * @return {@link Note#id} */ @Query("SELECT id FROM NOTE WHERE accountId = :accountId AND remoteId = :remoteId AND status != 'LOCAL_DELETED'") Long getLocalIdByRemoteId(long accountId, long remoteId); /** * Returns a list of all {@link Note}s in the Database which were modified locally * * @return {@link List} */ @Query("SELECT * FROM NOTE WHERE status != '' AND accountId = :accountId") List getLocalModifiedNotes(long accountId); @Query("SELECT * FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId ORDER BY modified DESC LIMIT 4") List getRecentNotes(long accountId); @Query("UPDATE NOTE SET status = 'LOCAL_EDITED', favorite = ((favorite | 1) - (favorite & 1)) WHERE id = :id") void toggleFavorite(long id); @Query("UPDATE NOTE SET remoteId = :remoteId WHERE id = :id") void updateRemoteId(long id, Long remoteId); /** * used by: {@link NoteServerSyncHelper.SyncTask#pushLocalChanges()} update only, if not modified locally during the synchronization * (i.e. all (!) user changeable columns (content, favorite, category) must still have the same value), uses reference value gathered at start of synchronization */ @Query("UPDATE NOTE SET title = :targetTitle, modified = :targetModified, favorite = :targetFavorite, etag = :targetETag, content = :targetContent, status = '', excerpt = :targetExcerpt " + "WHERE id = :noteId AND content = :contentBeforeSyncStart AND favorite = :favoriteBeforeSyncStart AND category = :categoryBeforeSyncStart") int updateIfNotModifiedLocallyDuringSync(long noteId, Long targetModified, String targetTitle, boolean targetFavorite, String targetETag, String targetContent, String targetExcerpt, String contentBeforeSyncStart, String categoryBeforeSyncStart, boolean favoriteBeforeSyncStart); /** * used by: {@link NoteServerSyncHelper.SyncTask#pullRemoteChanges()} update only, if not modified locally (i.e. STATUS="") and if modified remotely (i.e. any (!) column has changed) */ @Query("UPDATE NOTE SET title = :title, modified = :modified, favorite = :favorite, etag = :eTag, content = :content, status = '', excerpt = :excerpt " + "WHERE id = :id AND status = '' AND (title != :title OR modified != :modified OR favorite != :favorite OR category != :category OR (eTag IS NULL OR eTag != :eTag) OR content != :content)") int updateIfNotModifiedLocallyAndAnyRemoteColumnHasChanged(long id, Long modified, String title, boolean favorite, String category, String eTag, String content, String excerpt); /** * This method return all of the categories with given {@param accountId} * * @param accountId The user account Id * @return All of the categories with given accountId */ @Query("SELECT accountId, category, COUNT(*) as 'totalNotes' FROM NOTE WHERE STATUS != 'LOCAL_DELETED' AND accountId = :accountId GROUP BY category") LiveData> getCategories$(Long accountId); @Query("SELECT accountId, category, COUNT(*) as 'totalNotes' FROM NOTE WHERE STATUS != 'LOCAL_DELETED' AND accountId = :accountId AND category != '' AND category LIKE :searchTerm GROUP BY category") LiveData> searchCategories$(Long accountId, String searchTerm); }