1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-01 01:06:53 +01:00
fixed some NPEs
This commit is contained in:
Mariotaku Lee 2016-03-20 12:48:47 +08:00
parent 0fcf75b21e
commit d12e331583
26 changed files with 204 additions and 107 deletions

View File

@ -300,14 +300,12 @@ public interface TwidereDataStore {
String EXTRAS = "extras"; String EXTRAS = "extras";
String USER_HOST = "user_host";
String[] COLUMNS = {_ID, USER_KEY, CREATED_AT, NAME, SCREEN_NAME, DESCRIPTION_PLAIN, LOCATION, String[] COLUMNS = {_ID, USER_KEY, CREATED_AT, NAME, SCREEN_NAME, DESCRIPTION_PLAIN, LOCATION,
URL, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, PROFILE_BACKGROUND_URL, IS_PROTECTED, URL, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, PROFILE_BACKGROUND_URL, IS_PROTECTED,
IS_VERIFIED, IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT, IS_VERIFIED, IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT,
FAVORITES_COUNT, LISTED_COUNT, MEDIA_COUNT, DESCRIPTION_HTML, DESCRIPTION_EXPANDED, FAVORITES_COUNT, LISTED_COUNT, MEDIA_COUNT, DESCRIPTION_HTML, DESCRIPTION_EXPANDED,
URL_EXPANDED, BACKGROUND_COLOR, LINK_COLOR, TEXT_COLOR, LAST_SEEN, URL_EXPANDED, BACKGROUND_COLOR, LINK_COLOR, TEXT_COLOR, LAST_SEEN,
DESCRIPTION_UNESCAPED, EXTRAS, USER_HOST}; DESCRIPTION_UNESCAPED, EXTRAS};
String[] BASIC_COLUMNS = {_ID, USER_KEY, NAME, SCREEN_NAME, PROFILE_IMAGE_URL}; String[] BASIC_COLUMNS = {_ID, USER_KEY, NAME, SCREEN_NAME, PROFILE_IMAGE_URL};
@ -315,7 +313,7 @@ public interface TwidereDataStore {
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT}; TYPE_TEXT, TYPE_TEXT};
} }
@ -1006,8 +1004,7 @@ public interface TwidereDataStore {
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH); Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
String USER_KEY = "user_id";
String USER_ID = "user_id";
String FOLLOWING = "following"; String FOLLOWING = "following";
@ -1021,7 +1018,7 @@ public interface TwidereDataStore {
String RETWEET_ENABLED = "retweet_enabled"; String RETWEET_ENABLED = "retweet_enabled";
String[] COLUMNS = {_ID, ACCOUNT_KEY, USER_ID, FOLLOWING, FOLLOWED_BY, BLOCKING, String[] COLUMNS = {_ID, ACCOUNT_KEY, USER_KEY, FOLLOWING, FOLLOWED_BY, BLOCKING,
BLOCKED_BY, MUTING, RETWEET_ENABLED}; BLOCKED_BY, MUTING, RETWEET_ENABLED};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_TEXT_NOT_NULL, TYPE_TEXT_NOT_NULL, String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_TEXT_NOT_NULL, TYPE_TEXT_NOT_NULL,

View File

@ -3,6 +3,9 @@ package org.mariotaku.twidere.util;
import org.junit.Test; import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
/** /**
* Created by mariotaku on 16/1/31. * Created by mariotaku on 16/1/31.
*/ */
@ -10,5 +13,22 @@ public class TwidereArrayUtilsTest {
@Test @Test
public void testMergeArray() throws Exception { public void testMergeArray() throws Exception {
String[] array1 = {"1", "2"};
String[] array2 = {"1", "2"};
String[] array3 = null;
String[] merged = new String[TwidereArrayUtils.arraysLength(array1, array2, array3)];
TwidereArrayUtils.mergeArray(merged, array1, array2, array3);
String[] expected = {"1", "2", "1", "2"};
assertArrayEquals(expected, merged);
}
@Test
public void testArraysLength() throws Exception {
String[] array1 = {"1", "2"};
String[] array2 = {"1", "2"};
String[] array3 = null;
assertEquals(4, TwidereArrayUtils.arraysLength(array1, array2, array3));
assertEquals(6, TwidereArrayUtils.arraysLength(array1, array2, array2));
} }
} }

View File

@ -34,7 +34,7 @@ import static org.mariotaku.twidere.annotation.PreferenceType.STRING;
public interface Constants extends TwidereConstants { public interface Constants extends TwidereConstants {
String DATABASES_NAME = "twidere.sqlite"; String DATABASES_NAME = "twidere.sqlite";
int DATABASES_VERSION = 134; int DATABASES_VERSION = 135;
int MENU_GROUP_STATUS_EXTENSION = 10; int MENU_GROUP_STATUS_EXTENSION = 10;
int MENU_GROUP_COMPOSE_EXTENSION = 11; int MENU_GROUP_COMPOSE_EXTENSION = 11;

View File

@ -42,7 +42,6 @@ import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.UserColorNameManager; import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper; import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.view.ProfileImageView;
import javax.inject.Inject; import javax.inject.Inject;
@ -112,12 +111,15 @@ public class UserAutoCompleteAdapter extends SimpleCursorAdapter implements Cons
if (filter != null) return filter.runQuery(constraint); if (filter != null) return filter.runQuery(constraint);
final String query = constraint.toString(); final String query = constraint.toString();
final String queryEscaped = query.replace("_", "^_"); final String queryEscaped = query.replace("_", "^_");
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager); final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression usersSelection = Expression.or( final Expression usersSelection = Expression.or(
Expression.likeRaw(new Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"), Expression.likeRaw(new Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Columns.Column(CachedUsers.NAME), "?||'%'", "^"), Expression.likeRaw(new Columns.Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Columns.Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds))); Expression.inArgs(new Columns.Column(CachedUsers.USER_KEY), nicknameKeys.length));
final String[] selectionArgs = new String[]{queryEscaped, queryEscaped}; //TODO
final String[] selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME, final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME,
CachedUsers.NAME}; CachedUsers.NAME};
final boolean[] ascending = {false, false, true, true}; final boolean[] ascending = {false, false, true, true};

View File

@ -208,7 +208,7 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
@Nullable @Nullable
@Override @Override
public long[] getMaxSortIds() { public long[] getMaxSortIds() {
return DataStoreUtils.getOldestActivityMaxSortPositions(getActivity(), return DataStoreUtils.getOldestActivityMaxSortPositions(getContext(),
getContentUri(), getAccountKeys()); getContentUri(), getAccountKeys());
} }
@ -216,6 +216,11 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
public boolean hasMaxIds() { public boolean hasMaxIds() {
return true; return true;
} }
@Override
public boolean shouldAbort() {
return getContext() == null;
}
}); });
} }
@ -238,7 +243,7 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
@Nullable @Nullable
@Override @Override
public long[] getSinceSortIds() { public long[] getSinceSortIds() {
return DataStoreUtils.getNewestActivityMaxSortPositions(getActivity(), return DataStoreUtils.getNewestActivityMaxSortPositions(getContext(),
getContentUri(), getAccountKeys()); getContentUri(), getAccountKeys());
} }
@ -246,6 +251,11 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
public boolean hasSinceIds() { public boolean hasSinceIds() {
return true; return true;
} }
@Override
public boolean shouldAbort() {
return getContext() == null;
}
}); });
return true; return true;
} }

View File

@ -253,7 +253,6 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
// Only supports load from end, skip START flag // Only supports load from end, skip START flag
if ((position & IndicatorPosition.START) != 0) return; if ((position & IndicatorPosition.START) != 0) return;
super.onLoadMoreContents(position); super.onLoadMoreContents(position);
final Context context = getContext();
if (position == 0) return; if (position == 0) return;
getStatuses(new SimpleRefreshTaskParam() { getStatuses(new SimpleRefreshTaskParam() {
@NonNull @NonNull
@ -271,7 +270,7 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
@Nullable @Nullable
@Override @Override
public long[] getMaxSortIds() { public long[] getMaxSortIds() {
return DataStoreUtils.getOldestStatusSortIds(context, getContentUri(), return DataStoreUtils.getOldestStatusSortIds(getContext(), getContentUri(),
getAccountKeys()); getAccountKeys());
} }
@ -279,13 +278,17 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
public boolean hasMaxIds() { public boolean hasMaxIds() {
return true; return true;
} }
@Override
public boolean shouldAbort() {
return getContext() == null;
}
}); });
} }
@Override @Override
public boolean triggerRefresh() { public boolean triggerRefresh() {
super.triggerRefresh(); super.triggerRefresh();
final Context context = getContext();
getStatuses(new SimpleRefreshTaskParam() { getStatuses(new SimpleRefreshTaskParam() {
@NonNull @NonNull
@Override @Override
@ -307,9 +310,14 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
@Nullable @Nullable
@Override @Override
public long[] getSinceSortIds() { public long[] getSinceSortIds() {
return DataStoreUtils.getNewestStatusSortIds(context, getContentUri(), return DataStoreUtils.getNewestStatusSortIds(getContext(), getContentUri(),
getAccountKeys()); getAccountKeys());
} }
@Override
public boolean shouldAbort() {
return getContext() == null;
}
}); });
return true; return true;
} }

View File

@ -864,11 +864,13 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
final Expression selection; final Expression selection;
final String[] selectionArgs; final String[] selectionArgs;
if (queryEscaped != null) { if (queryEscaped != null) {
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager); final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
selection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"), selection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"), Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds))); Expression.inArgs(new Column(CachedUsers.USER_KEY), nicknameKeys.length));
selectionArgs = new String[]{queryEscaped, queryEscaped}; selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
} else { } else {
selection = null; selection = null;
selectionArgs = null; selectionArgs = null;

View File

@ -158,7 +158,7 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment {
final String[] maxIds = {status.id}; final String[] maxIds = {status.id};
mPage += mPageDelta; mPage += mPageDelta;
final BaseRefreshTaskParam param = new BaseRefreshTaskParam(accountKeys, maxIds, null); final BaseRefreshTaskParam param = new BaseRefreshTaskParam(accountKeys, maxIds, null);
param.setIsLoadingMore(true); param.setLoadingMore(true);
getStatuses(param); getStatuses(param);
} }

View File

@ -244,6 +244,7 @@ public abstract class ParcelableUsersFragment extends AbsContentListRecyclerView
final ParcelableUsersAdapter adapter = getAdapter(); final ParcelableUsersAdapter adapter = getAdapter();
final int position = findPosition(adapter, event.getAccountKey(), event.getUserKey()); final int position = findPosition(adapter, event.getAccountKey(), event.getUserKey());
final List<ParcelableUser> data = adapter.getData(); final List<ParcelableUser> data = adapter.getData();
if (position < 0 || position >= data.size()) return;
if (shouldRemoveUser(position, event)) { if (shouldRemoveUser(position, event)) {
data.remove(position); data.remove(position);
adapter.notifyItemRemoved(position); adapter.notifyItemRemoved(position);

View File

@ -1825,7 +1825,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
return SingleResponse.getInstance(new TwitterException("No Account")); return SingleResponse.getInstance(new TwitterException("No Account"));
} }
final boolean isFiltering = DataStoreUtils.isFilteringUser(context, mUserId); final boolean isFiltering = DataStoreUtils.isFilteringUser(context, mUserId);
if (mAccountKey.getId() == mUserId) if (mAccountKey.getId().equals(mUserId))
return SingleResponse.getInstance(); return SingleResponse.getInstance();
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountKey, false); final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountKey, false);
if (twitter == null) { if (twitter == null) {
@ -1839,7 +1839,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
} else { } else {
Utils.setLastSeen(context, userKey, System.currentTimeMillis()); Utils.setLastSeen(context, userKey, System.currentTimeMillis());
} }
Utils.updateRelationship(context, relationship, mAccountKey); Utils.updateRelationship(context, mAccountKey, userKey, relationship);
return SingleResponse.getInstance(new UserRelationship(relationship, isFiltering)); return SingleResponse.getInstance(new UserRelationship(relationship, isFiltering));
} catch (final TwitterException e) { } catch (final TwitterException e) {
return SingleResponse.getInstance(e); return SingleResponse.getInstance(e);

View File

@ -14,6 +14,7 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
private final long[] maxSortIds; private final long[] maxSortIds;
private final long[] sinceSortIds; private final long[] sinceSortIds;
private boolean isLoadingMore; private boolean isLoadingMore;
private boolean shouldAbort;
public BaseRefreshTaskParam(UserKey[] accountKeys, String[] maxIds, String[] sinceIds) { public BaseRefreshTaskParam(UserKey[] accountKeys, String[] maxIds, String[] sinceIds) {
this(accountKeys, maxIds, sinceIds, null, null); this(accountKeys, maxIds, sinceIds, null, null);
@ -71,7 +72,16 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
return isLoadingMore; return isLoadingMore;
} }
public void setIsLoadingMore(boolean isLoadingMore) { public void setLoadingMore(boolean isLoadingMore) {
this.isLoadingMore = isLoadingMore; this.isLoadingMore = isLoadingMore;
} }
@Override
public boolean shouldAbort() {
return shouldAbort;
}
public void setShouldAbort(boolean shouldAbort) {
this.shouldAbort = shouldAbort;
}
} }

View File

@ -16,7 +16,7 @@ public class CachedRelationship {
@CursorField(CachedRelationships.ACCOUNT_KEY) @CursorField(CachedRelationships.ACCOUNT_KEY)
public UserKey account_key; public UserKey account_key;
@CursorField(CachedRelationships.USER_ID) @CursorField(CachedRelationships.USER_KEY)
public String user_id; public String user_id;
@CursorField(CachedRelationships.FOLLOWING) @CursorField(CachedRelationships.FOLLOWING)

View File

@ -28,4 +28,6 @@ public interface RefreshTaskParam {
boolean isLoadingMore(); boolean isLoadingMore();
boolean shouldAbort();
} }

View File

@ -58,4 +58,9 @@ public abstract class SimpleRefreshTaskParam implements RefreshTaskParam {
public boolean isLoadingMore() { public boolean isLoadingMore() {
return false; return false;
} }
@Override
public boolean shouldAbort() {
return false;
}
} }

View File

@ -469,52 +469,63 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
return null; return null;
} }
final long rowId; final long rowId;
if (tableId == TABLE_ID_CACHED_USERS) { switch (tableId) {
final Expression where = Expression.and(Expression.equalsArgs(CachedUsers.USER_KEY), case TABLE_ID_CACHED_USERS: {
Expression.equalsArgs(CachedUsers.USER_HOST)); final Expression where = Expression.equalsArgs(CachedUsers.USER_KEY);
final String[] whereArgs = {values.getAsString(CachedUsers.USER_KEY), final String[] whereArgs = {values.getAsString(CachedUsers.USER_KEY)};
values.getAsString(CachedUsers.USER_HOST)}; mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs);
mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
} else if (tableId == TABLE_ID_SEARCH_HISTORY) {
values.put(SearchHistory.RECENT_QUERY, System.currentTimeMillis());
final Expression where = Expression.equalsArgs(SearchHistory.QUERY);
final String[] args = {values.getAsString(SearchHistory.QUERY)};
mDatabaseWrapper.update(table, values, where.getSQL(), args);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
} else if (tableId == TABLE_ID_CACHED_RELATIONSHIPS) {
final String accountKey = values.getAsString(CachedRelationships.ACCOUNT_KEY);
final String userId = values.getAsString(CachedRelationships.USER_ID);
final Expression where = Expression.and(
Expression.equalsArgs(CachedRelationships.ACCOUNT_KEY),
Expression.equalsArgs(CachedRelationships.USER_ID)
);
final String[] whereArgs = {accountKey, userId};
if (mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs) > 0) {
final String[] projection = {CachedRelationships._ID};
final Cursor c = mDatabaseWrapper.query(table, projection, where.getSQL(), null,
null, null, null);
if (c.moveToFirst()) {
rowId = c.getLong(0);
} else {
rowId = 0;
}
c.close();
} else {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values, rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE); SQLiteDatabase.CONFLICT_IGNORE);
break;
}
case TABLE_ID_SEARCH_HISTORY: {
values.put(SearchHistory.RECENT_QUERY, System.currentTimeMillis());
final Expression where = Expression.equalsArgs(SearchHistory.QUERY);
final String[] args = {values.getAsString(SearchHistory.QUERY)};
mDatabaseWrapper.update(table, values, where.getSQL(), args);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
break;
}
case TABLE_ID_CACHED_RELATIONSHIPS: {
final String accountKey = values.getAsString(CachedRelationships.ACCOUNT_KEY);
final String userId = values.getAsString(CachedRelationships.USER_KEY);
final Expression where = Expression.and(
Expression.equalsArgs(CachedRelationships.ACCOUNT_KEY),
Expression.equalsArgs(CachedRelationships.USER_KEY)
);
final String[] whereArgs = {accountKey, userId};
if (mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs) > 0) {
final String[] projection = {CachedRelationships._ID};
final Cursor c = mDatabaseWrapper.query(table, projection, where.getSQL(), null,
null, null, null);
if (c.moveToFirst()) {
rowId = c.getLong(0);
} else {
rowId = 0;
}
c.close();
} else {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
}
break;
}
case VIRTUAL_TABLE_ID_DRAFTS_NOTIFICATIONS: {
rowId = showDraftNotification(values);
break;
}
default: {
if (shouldReplaceOnConflict(tableId)) {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_REPLACE);
} else if (table != null) {
rowId = mDatabaseWrapper.insert(table, null, values);
} else {
return null;
}
break;
} }
} else if (tableId == VIRTUAL_TABLE_ID_DRAFTS_NOTIFICATIONS) {
rowId = showDraftNotification(values);
} else if (shouldReplaceOnConflict(tableId)) {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_REPLACE);
} else if (table != null) {
rowId = mDatabaseWrapper.insert(table, null, values);
} else {
return null;
} }
onDatabaseUpdated(tableId, uri); onDatabaseUpdated(tableId, uri);
onNewItemsInserted(uri, tableId, values); onNewItemsInserted(uri, tableId, values);
@ -729,7 +740,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_RELATIONSHIP: { case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_RELATIONSHIP: {
final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment()); final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment());
final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withRelationship(projection, final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withRelationship(projection,
selection, sortOrder, accountKey); selection, selectionArgs, sortOrder, accountKey);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second); final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, CachedUsers.CONTENT_URI); setNotificationUri(c, CachedUsers.CONTENT_URI);
return c; return c;
@ -737,7 +748,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_SCORE: { case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_SCORE: {
final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment()); final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment());
final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withScore(projection, final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withScore(projection,
selection, sortOrder, accountKey, 0); selection, selectionArgs, sortOrder, accountKey, 0);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second); final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, CachedUsers.CONTENT_URI); setNotificationUri(c, CachedUsers.CONTENT_URI);
return c; return c;
@ -834,19 +845,21 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
new Column(CachedUsers.SCREEN_NAME, Suggestions.Search.VALUE).getSQL(), new Column(CachedUsers.SCREEN_NAME, Suggestions.Search.VALUE).getSQL(),
}; };
String queryTrimmed = queryEscaped.startsWith("@") ? queryEscaped.substring(1) : queryEscaped; String queryTrimmed = queryEscaped.startsWith("@") ? queryEscaped.substring(1) : queryEscaped;
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager); final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression usersSelection = Expression.or( final Expression usersSelection = Expression.or(
Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"), Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"), Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds))); Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameKeys)));
final String[] selectionArgs = new String[]{queryTrimmed, queryTrimmed}; final String[] selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryTrimmed;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME, final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME,
CachedUsers.NAME}; CachedUsers.NAME};
final boolean[] ascending = {false, false, true, true}; final boolean[] ascending = {false, false, true, true};
final OrderBy orderBy = new OrderBy(order, ascending); final OrderBy orderBy = new OrderBy(order, ascending);
final Pair<SQLSelectQuery, String[]> usersQuery = CachedUsersQueryBuilder.withScore(usersProjection, final Pair<SQLSelectQuery, String[]> usersQuery = CachedUsersQueryBuilder.withScore(usersProjection,
usersSelection.getSQL(), orderBy.getSQL(), accountKey, 0); usersSelection.getSQL(), selectionArgs, orderBy.getSQL(), accountKey, 0);
@SuppressLint("Recycle") final Cursor usersCursor = mDatabaseWrapper.rawQuery(usersQuery.first.getSQL(), usersQuery.second); @SuppressLint("Recycle") final Cursor usersCursor = mDatabaseWrapper.rawQuery(usersQuery.first.getSQL(), usersQuery.second);
final Expression exactUserSelection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?", "^")); final Expression exactUserSelection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?", "^"));
final Cursor exactUserCursor = mDatabaseWrapper.query(CachedUsers.TABLE_NAME, final Cursor exactUserCursor = mDatabaseWrapper.query(CachedUsers.TABLE_NAME,
@ -878,11 +891,13 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
if (query == null || type == null) return null; if (query == null || type == null) return null;
final String queryEscaped = query.replace("_", "^_"); final String queryEscaped = query.replace("_", "^_");
if (Suggestions.AutoComplete.TYPE_USERS.equals(type)) { if (Suggestions.AutoComplete.TYPE_USERS.equals(type)) {
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager); final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression where = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"), final Expression where = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"), Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds))); Expression.inArgs(new Column(CachedUsers.USER_KEY), nicknameKeys.length));
final String[] whereArgs = {queryEscaped, queryEscaped}; final String[] whereArgs = new String[nicknameKeys.length + 2];
whereArgs[0] = whereArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, whereArgs, 2, nicknameKeys.length);
final String[] mappedProjection = { final String[] mappedProjection = {
new Column(CachedUsers._ID, Suggestions._ID).getSQL(), new Column(CachedUsers._ID, Suggestions._ID).getSQL(),
new Column("'" + Suggestions.AutoComplete.TYPE_USERS + "'", Suggestions.TYPE).getSQL(), new Column("'" + Suggestions.AutoComplete.TYPE_USERS + "'", Suggestions.TYPE).getSQL(),

View File

@ -59,7 +59,7 @@ public class CreateUserBlockTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list. // I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString()); values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString()); values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.BLOCKING, true); values.put(CachedRelationships.BLOCKING, true);
values.put(CachedRelationships.FOLLOWING, false); values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false); values.put(CachedRelationships.FOLLOWED_BY, false);

View File

@ -53,7 +53,7 @@ public class CreateUserMuteTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list. // I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString()); values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString()); values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.MUTING, true); values.put(CachedRelationships.MUTING, true);
resolver.insert(CachedRelationships.CONTENT_URI, values); resolver.insert(CachedRelationships.CONTENT_URI, values);
} }

View File

@ -46,7 +46,7 @@ public class DestroyUserBlockTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list. // I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString()); values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString()); values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.BLOCKING, false); values.put(CachedRelationships.BLOCKING, false);
values.put(CachedRelationships.FOLLOWING, false); values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false); values.put(CachedRelationships.FOLLOWED_BY, false);

View File

@ -39,7 +39,7 @@ public class DestroyUserMuteTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list. // I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString()); values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString()); values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.MUTING, false); values.put(CachedRelationships.MUTING, false);
resolver.insert(CachedRelationships.CONTENT_URI, values); resolver.insert(CachedRelationships.CONTENT_URI, values);
} }

View File

@ -64,6 +64,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
@Override @Override
public Object doLongOperation(RefreshTaskParam param) { public Object doLongOperation(RefreshTaskParam param) {
if (param.shouldAbort()) return null;
final UserKey[] accountIds = param.getAccountKeys(); final UserKey[] accountIds = param.getAccountKeys();
final String[] maxIds = param.getMaxIds(); final String[] maxIds = param.getMaxIds();
final String[] sinceIds = param.getSinceIds(); final String[] sinceIds = param.getSinceIds();

View File

@ -807,7 +807,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
values.put(CachedRelationships.BLOCKING, true); values.put(CachedRelationships.BLOCKING, true);
values.put(CachedRelationships.FOLLOWING, false); values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false); values.put(CachedRelationships.FOLLOWED_BY, false);
final String where = Expression.inArgs(CachedRelationships.USER_ID, list.size()).getSQL(); final String where = Expression.inArgs(CachedRelationships.USER_KEY, list.size()).getSQL();
final String[] selectionArgs = list.toArray(new String[list.size()]); final String[] selectionArgs = list.toArray(new String[list.size()]);
mResolver.update(CachedRelationships.CONTENT_URI, values, where, selectionArgs); mResolver.update(CachedRelationships.CONTENT_URI, values, where, selectionArgs);
} }

View File

@ -65,10 +65,11 @@ import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
public final class ContentValuesCreator implements TwidereConstants { public final class ContentValuesCreator implements TwidereConstants {
public static ContentValues createCachedRelationship(final Relationship relationship, public static ContentValues createCachedRelationship(final Relationship relationship,
final UserKey accountKey) { final UserKey accountKey,
final UserKey userKey) {
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, accountKey.toString()); values.put(CachedRelationships.ACCOUNT_KEY, accountKey.toString());
values.put(CachedRelationships.USER_ID, relationship.getTargetUserId()); values.put(CachedRelationships.USER_KEY, userKey.toString());
values.put(CachedRelationships.FOLLOWING, relationship.isSourceFollowingTarget()); values.put(CachedRelationships.FOLLOWING, relationship.isSourceFollowingTarget());
values.put(CachedRelationships.FOLLOWED_BY, relationship.isSourceFollowedByTarget()); values.put(CachedRelationships.FOLLOWED_BY, relationship.isSourceFollowedByTarget());
values.put(CachedRelationships.BLOCKING, relationship.isSourceBlockingTarget()); values.put(CachedRelationships.BLOCKING, relationship.isSourceBlockingTarget());

View File

@ -96,11 +96,21 @@ public final class TwidereArrayUtils {
return list1.toArray((T[]) Array.newInstance(array1.getClass().getComponentType(), list1.size())); return list1.toArray((T[]) Array.newInstance(array1.getClass().getComponentType(), list1.size()));
} }
@SuppressWarnings("SuspiciousSystemArraycopy") public static int arraysLength(@NonNull final Object... arrays) {
int length = 0;
for (Object array : arrays) {
if (array == null) continue;
length += Array.getLength(array);
}
return length;
}
public static void mergeArray(final Object dest, @NonNull final Object... arrays) { public static void mergeArray(final Object dest, @NonNull final Object... arrays) {
for (int i = 0, j = arrays.length, k = 0; i < j; i++) { for (int i = 0, j = arrays.length, k = 0; i < j; i++) {
final Object array = arrays[i]; final Object array = arrays[i];
if (array == null) continue;
final int length = Array.getLength(array); final int length = Array.getLength(array);
//noinspection SuspiciousSystemArraycopy
System.arraycopy(array, 0, dest, k, length); System.arraycopy(array, 0, dest, k, length);
k += length; k += length;
} }

View File

@ -49,22 +49,24 @@ public class TwidereQueryBuilder {
public static Pair<SQLSelectQuery, String[]> withRelationship(final String[] projection, public static Pair<SQLSelectQuery, String[]> withRelationship(final String[] projection,
final String selection, final String selection,
final String[] selectionArgs,
final String sortOrder, final String sortOrder,
final UserKey accountKey) { final UserKey accountKey) {
return withRelationship(Utils.getColumnsFromProjection(projection), selection, return withRelationship(Utils.getColumnsFromProjection(projection), selection,
sortOrder, accountKey); selectionArgs, sortOrder, accountKey);
} }
public static Pair<SQLSelectQuery, String[]> withRelationship(final Selectable select, public static Pair<SQLSelectQuery, String[]> withRelationship(final Selectable select,
final String selection, final String selection,
final String[] selectionArgs,
final String sortOrder, final String sortOrder,
final UserKey accountKey) { final UserKey accountKey) {
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder(); final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
qb.select(select).from(new Tables(CachedUsers.TABLE_NAME)); qb.select(select).from(new Tables(CachedUsers.TABLE_NAME));
final Column relationshipsUserId = new Column(new Table(CachedRelationships.TABLE_NAME), final Column relationshipsUserId = new Column(new Table(CachedRelationships.TABLE_NAME),
CachedRelationships.USER_ID); CachedRelationships.USER_KEY);
final Column usersUserId = new Column(new Table(CachedUsers.TABLE_NAME), final Column usersUserId = new Column(new Table(CachedUsers.TABLE_NAME),
CachedRelationships.USER_ID); CachedRelationships.USER_KEY);
final Column relationshipsAccountId = new Column(new Table(CachedRelationships.TABLE_NAME), final Column relationshipsAccountId = new Column(new Table(CachedRelationships.TABLE_NAME),
CachedRelationships.ACCOUNT_KEY); CachedRelationships.ACCOUNT_KEY);
final Expression on = Expression.and( final Expression on = Expression.and(
@ -78,11 +80,17 @@ public class TwidereQueryBuilder {
if (sortOrder != null) { if (sortOrder != null) {
qb.orderBy(new OrderBy(sortOrder)); qb.orderBy(new OrderBy(sortOrder));
} }
return Pair.create(qb.build(), new String[]{accountKey.toString()}); final String[] accountKeyArgs = {accountKey.toString()};
final String[] mergedArgs = new String[TwidereArrayUtils.arraysLength(accountKeyArgs, selectionArgs)];
TwidereArrayUtils.mergeArray(mergedArgs, accountKeyArgs, selectionArgs);
return Pair.create(qb.build(), mergedArgs);
} }
public static Pair<SQLSelectQuery, String[]> withScore(final String[] projection, final String selection, public static Pair<SQLSelectQuery, String[]> withScore(final String[] projection,
final String sortOrder, final UserKey accountKey, final String selection,
final String[] selectionArgs,
final String sortOrder,
final UserKey accountKey,
final int limit) { final int limit) {
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder(); final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
final Selectable select = Utils.getColumnsFromProjection(projection); final Selectable select = Utils.getColumnsFromProjection(projection);
@ -101,8 +109,11 @@ public class TwidereQueryBuilder {
CachedRelationships.MUTING)); CachedRelationships.MUTING));
columns[columns.length - 1] = new Column(expr, "score"); columns[columns.length - 1] = new Column(expr, "score");
qb.select(select); qb.select(select);
final Pair<SQLSelectQuery, String[]> pair = withRelationship(new Columns(columns), null, null, accountKey); final Pair<SQLSelectQuery, String[]> pair = withRelationship(new Columns(columns), null,
null, null, accountKey);
qb.from(pair.first); qb.from(pair.first);
final String[] mergedArgs = new String[TwidereArrayUtils.arraysLength(pair.second, selectionArgs)];
TwidereArrayUtils.mergeArray(mergedArgs, pair.second, selectionArgs);
if (selection != null) { if (selection != null) {
qb.where(new Expression(selection)); qb.where(new Expression(selection));
} }
@ -112,7 +123,7 @@ public class TwidereQueryBuilder {
if (limit > 0) { if (limit > 0) {
qb.limit(limit); qb.limit(limit);
} }
return Pair.create(qb.build(), pair.second); return Pair.create(qb.build(), mergedArgs);
} }
private static Object[] valueOrZero(String... columns) { private static Object[] valueOrZero(String... columns) {

View File

@ -1322,21 +1322,21 @@ public final class Utils implements Constants {
return nf.format(number); return nf.format(number);
} }
public static long[] getMatchedNicknameIds(final String str, UserColorNameManager manager) { @NonNull
if (isEmpty(str)) return new long[0]; public static String[] getMatchedNicknameKeys(final String str, UserColorNameManager manager) {
final List<Long> list = new ArrayList<>(); if (isEmpty(str)) return new String[0];
final List<String> list = new ArrayList<>();
for (final Entry<String, ?> entry : manager.getNameEntries()) { for (final Entry<String, ?> entry : manager.getNameEntries()) {
final String value = ParseUtils.parseString(entry.getValue()); final String value = ParseUtils.parseString(entry.getValue());
final long def = -1; final String key = entry.getKey();
final long key = NumberUtils.toLong(entry.getKey(), def); if (isEmpty(key) || isEmpty(value)) {
if (key == -1 || isEmpty(value)) {
continue; continue;
} }
if (TwidereStringUtils.startsWithIgnoreCase(value, str)) { if (TwidereStringUtils.startsWithIgnoreCase(value, str)) {
list.add(key); list.add(key);
} }
} }
return TwidereArrayUtils.fromList(list); return list.toArray(new String[list.size()]);
} }
@NonNull @NonNull
@ -1994,9 +1994,11 @@ public final class Utils implements Constants {
return orig.replaceAll("\\n+", "\n"); return orig.replaceAll("\\n+", "\n");
} }
public static void updateRelationship(Context context, Relationship relationship, UserKey accountId) { public static void updateRelationship(Context context, UserKey accountKey, UserKey userKey,
Relationship relationship) {
final ContentResolver resolver = context.getContentResolver(); final ContentResolver resolver = context.getContentResolver();
final ContentValues values = ContentValuesCreator.createCachedRelationship(relationship, accountId); final ContentValues values = ContentValuesCreator.createCachedRelationship(relationship,
accountKey, userKey);
resolver.insert(CachedRelationships.CONTENT_URI, values); resolver.insert(CachedRelationships.CONTENT_URI, values);
} }

View File

@ -83,11 +83,11 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
db.execSQL(createTable(Activities.ByFriends.TABLE_NAME, Activities.ByFriends.COLUMNS, Activities.ByFriends.TYPES, true)); db.execSQL(createTable(Activities.ByFriends.TABLE_NAME, Activities.ByFriends.COLUMNS, Activities.ByFriends.TYPES, true));
db.execSQL(createTable(Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, true)); db.execSQL(createTable(Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, true));
db.execSQL(createTable(CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true, db.execSQL(createTable(CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true,
createConflictReplaceConstraint(CachedUsers.USER_KEY, CachedUsers.USER_HOST))); createConflictReplaceConstraint(CachedUsers.USER_KEY)));
db.execSQL(createTable(CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, true)); db.execSQL(createTable(CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, true));
db.execSQL(createTable(CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, true)); db.execSQL(createTable(CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, true));
db.execSQL(createTable(CachedRelationships.TABLE_NAME, CachedRelationships.COLUMNS, CachedRelationships.TYPES, true, db.execSQL(createTable(CachedRelationships.TABLE_NAME, CachedRelationships.COLUMNS, CachedRelationships.TYPES, true,
createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_ID))); createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_KEY)));
db.execSQL(createTable(Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES, true)); db.execSQL(createTable(Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES, true));
db.execSQL(createTable(Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES, true)); db.execSQL(createTable(Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES, true));
db.execSQL(createTable(Filters.Sources.TABLE_NAME, Filters.Sources.COLUMNS, Filters.Sources.TYPES, true)); db.execSQL(createTable(Filters.Sources.TABLE_NAME, Filters.Sources.COLUMNS, Filters.Sources.TYPES, true));
@ -234,11 +234,11 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
Activities.ByFriends.TYPES, true, null); Activities.ByFriends.TYPES, true, null);
safeUpgrade(db, Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, false, draftsAlias); safeUpgrade(db, Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, false, draftsAlias);
safeUpgrade(db, CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true, null, safeUpgrade(db, CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true, null,
createConflictReplaceConstraint(CachedUsers.USER_KEY, CachedUsers.USER_HOST)); createConflictReplaceConstraint(CachedUsers.USER_KEY));
safeUpgrade(db, CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, true, null); safeUpgrade(db, CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, true, null);
safeUpgrade(db, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, true, null); safeUpgrade(db, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, true, null);
safeUpgrade(db, CachedRelationships.TABLE_NAME, CachedRelationships.COLUMNS, CachedRelationships.TYPES, true, null, safeUpgrade(db, CachedRelationships.TABLE_NAME, CachedRelationships.COLUMNS, CachedRelationships.TYPES, true, null,
createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_ID)); createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_KEY));
safeUpgrade(db, Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES, safeUpgrade(db, Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES,
oldVersion < 49, null); oldVersion < 49, null);
safeUpgrade(db, Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES, safeUpgrade(db, Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES,