Skip to content

Commit

Permalink
NOT TESTED!
Browse files Browse the repository at this point in the history
improved database upgrade speed.
  • Loading branch information
mariotaku committed Jul 3, 2012
1 parent 6c7e834 commit b82dc5a
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 132 deletions.
17 changes: 15 additions & 2 deletions src/com/twitter/Extractor.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,18 @@ public List<Entity> extractEntitiesWithIndices(String text) {
* @return List of hashtags referenced (without the leading # sign)
*/
public List<String> extractHashtags(String text) {
return extractHashtags(text, true);
}


public List<String> extractHashtags(String text, boolean exclude_duplicate) {
if (text == null || text.length() == 0) return Collections.emptyList();

final List<String> extracted = new ArrayList<String>();
for (final Entity entity : extractHashtagsWithIndices(text)) {
extracted.add(entity.value);
if (!exclude_duplicate || !extracted.contains(entity.value)) {
extracted.add(entity.value);
}
}

return extracted;
Expand All @@ -112,11 +119,17 @@ public List<Entity> extractHashtagsWithIndices(String text) {
* @return List of usernames referenced (without the leading @ sign)
*/
public List<String> extractMentionedScreennames(String text) {
return extractMentionedScreennames(text, true);
}

public List<String> extractMentionedScreennames(String text, boolean exclude_duplicate) {
if (text == null || text.length() == 0) return Collections.emptyList();

final List<String> extracted = new ArrayList<String>();
for (final Entity entity : extractMentionedScreennamesWithIndices(text)) {
extracted.add(entity.value);
if (!exclude_duplicate || !extracted.contains(entity.value)) {
extracted.add(entity.value);
}
}
return extracted;
}
Expand Down
2 changes: 1 addition & 1 deletion src/org/mariotaku/twidere/activity/HomeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public boolean checkDefaultAccountSet() {
boolean result = true;
final long[] activated_ids = getActivatedAccountIds(this);
final long default_account_id = mPreferences.getLong(PREFERENCE_KEY_DEFAULT_ACCOUNT_ID, -1);
if (default_account_id == -1 || !ArrayUtils.contains(activated_ids, default_account_id)) {
if (default_account_id == -1 || !ArrayUtils.containsLong(activated_ids, default_account_id)) {
if (activated_ids.length == 1) {
mPreferences.edit().putLong(PREFERENCE_KEY_DEFAULT_ACCOUNT_ID, activated_ids[0]).commit();
mIndicator.setPagingEnabled(true);
Expand Down
139 changes: 11 additions & 128 deletions src/org/mariotaku/twidere/provider/TweetStoreProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static org.mariotaku.twidere.util.Utils.getTableId;
import static org.mariotaku.twidere.util.Utils.getTableNameForContentUri;

import static org.mariotaku.twidere.util.DatabaseUpgradeHelper.safeUpgrade;

import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -117,16 +119,6 @@ private void onDatabaseUpdated(Uri uri, boolean is_insert) {

public static class DatabaseHelper extends SQLiteOpenHelper {

private static final int FIELD_TYPE_NULL = 0;

private static final int FIELD_TYPE_INTEGER = 1;

private static final int FIELD_TYPE_FLOAT = 2;

private static final int FIELD_TYPE_STRING = 3;

private static final int FIELD_TYPE_BLOB = 4;

public DatabaseHelper(Context context, String name, int version) {
super(context, name, null, version);
}
Expand Down Expand Up @@ -174,127 +166,18 @@ private String createTable(String tableName, String[] columns, String[] types, b
return stringBuilder.append(");").toString();
}

private int getTypeInt(String type) {
final int idx = type.contains("(") ? type.indexOf("(") : type.indexOf(" ");
final String type_main = idx > -1 ? type.substring(0, idx) : type;
if ("NULL".equalsIgnoreCase(type_main))
return FIELD_TYPE_NULL;
else if ("INTEGER".equalsIgnoreCase(type_main))
return FIELD_TYPE_INTEGER;
else if ("FLOAT".equalsIgnoreCase(type_main))
return FIELD_TYPE_FLOAT;
else if ("TEXT".equalsIgnoreCase(type_main))
return FIELD_TYPE_STRING;
else if ("BLOB".equalsIgnoreCase(type_main)) return FIELD_TYPE_BLOB;
throw new IllegalStateException("Unknown field type " + type + " !");
}

private String getTypeString(SQLiteDatabase db, String table, String column) {

final String sql = "SELECT typeof(" + column + ") FROM " + table;
final Cursor cur = db.rawQuery(sql, null);
if (cur == null) return null;

cur.moveToFirst();
final String type = cur.getString(0);
cur.close();
return type;

}

private void handleVersionChange(SQLiteDatabase db) {
safeVersionChange(db, TABLE_ACCOUNTS, Accounts.COLUMNS, Accounts.TYPES);
safeVersionChange(db, TABLE_STATUSES, Statuses.COLUMNS, Statuses.TYPES);
safeVersionChange(db, TABLE_MENTIONS, Mentions.COLUMNS, Mentions.TYPES);
safeVersionChange(db, TABLE_DRAFTS, Drafts.COLUMNS, Drafts.TYPES);
safeVersionChange(db, TABLE_CACHED_USERS, CachedUsers.COLUMNS, CachedUsers.TYPES);
safeVersionChange(db, TABLE_FILTERED_USERS, Filters.Users.COLUMNS, Filters.Users.TYPES);
safeVersionChange(db, TABLE_FILTERED_KEYWORDS, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES);
safeVersionChange(db, TABLE_FILTERED_SOURCES, Filters.Sources.COLUMNS, Filters.Sources.TYPES);
}

private boolean isColumnContained(String[] cols, String col) {
for (final String tmp_col : cols)
if (col.equals(tmp_col)) return true;
return false;
safeUpgrade(db, TABLE_ACCOUNTS, Accounts.COLUMNS, Accounts.TYPES, true);
safeUpgrade(db, TABLE_STATUSES, Statuses.COLUMNS, Statuses.TYPES, true);
safeUpgrade(db, TABLE_MENTIONS, Mentions.COLUMNS, Mentions.TYPES, true);
safeUpgrade(db, TABLE_DRAFTS, Drafts.COLUMNS, Drafts.TYPES, true);
safeUpgrade(db, TABLE_CACHED_USERS, CachedUsers.COLUMNS, CachedUsers.TYPES, true);
safeUpgrade(db, TABLE_FILTERED_USERS, Filters.Users.COLUMNS, Filters.Users.TYPES, true);
safeUpgrade(db, TABLE_FILTERED_KEYWORDS, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES, true);
safeUpgrade(db, TABLE_FILTERED_SOURCES, Filters.Sources.COLUMNS, Filters.Sources.TYPES, true);
}

private boolean isTypeCompatible(String old_type, String new_type) {
if (old_type != null && new_type != null) {
final int old_idx = old_type.contains("(") ? old_type.indexOf("(") : old_type.indexOf(" ");
final int new_idx = new_type.contains("(") ? new_type.indexOf("(") : new_type.indexOf(" ");
final String old_type_main = old_idx > -1 ? old_type.substring(0, old_idx) : old_type;
final String new_type_main = new_idx > -1 ? new_type.substring(0, new_idx) : new_type;
return old_type_main.equalsIgnoreCase(new_type_main);
}
return false;
}

private void safeVersionChange(SQLiteDatabase db, String table, String[] new_cols, String[] new_types) {

if (new_cols == null || new_types == null || new_cols.length != new_types.length)
throw new IllegalArgumentException("Invalid parameters, length of columns and types not match.");

// First, create the table if not exists.
db.execSQL(createTable(table, new_cols, new_types, true));

// We need to get all data from old table.
final Cursor cur = db.query(table, null, null, null, null, null, null);
cur.moveToFirst();
final String[] old_cols = cur.getColumnNames();

final List<ContentValues> values_list = new ArrayList<ContentValues>();

while (!cur.isAfterLast()) {
final ContentValues values = new ContentValues();
for (int i = 0; i < new_cols.length; i++) {
final String new_col = new_cols[i];
final String new_type = new_types[i];
if (BaseColumns._ID.equals(new_col)) {
continue;
}

final int idx = cur.getColumnIndex(new_col);

if (isColumnContained(old_cols, new_col)) {
final String old_type = getTypeString(db, table, new_col);
final boolean compatible = isTypeCompatible(old_type, new_type);
if (compatible && idx > -1) {
switch (getTypeInt(new_type)) {
case FIELD_TYPE_INTEGER:
values.put(new_col, cur.getLong(idx));
break;
case FIELD_TYPE_FLOAT:
values.put(new_col, cur.getFloat(idx));
break;
case FIELD_TYPE_STRING:
values.put(new_col, cur.getString(idx));
break;
case FIELD_TYPE_BLOB:
values.put(new_col, cur.getBlob(idx));
break;
case FIELD_TYPE_NULL:
default:
break;
}
}
}

}
values_list.add(values);
cur.moveToNext();
}
cur.close();
// OK, now we got all data can be moved from old table, so we will
// delete the old table and create a new one.
db.execSQL("DROP TABLE IF EXISTS " + table);
db.execSQL(createTable(table, new_cols, new_types, false));

// Now, insert all data backuped into new table.
for (final ContentValues values : values_list) {
db.insert(table, null, values);
}
}


}

Expand Down
28 changes: 27 additions & 1 deletion src/org/mariotaku/twidere/util/ArrayUtils.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.mariotaku.twidere.util;
import java.util.Arrays;

public final class ArrayUtils {

private ArrayUtils() {
throw new IllegalArgumentException("You are trying to create an instance for this utility class!");
}

public static String buildString(long[] array, char token, boolean include_space) {
Expand All @@ -19,17 +21,41 @@ public static String buildString(long[] array, char token, boolean include_space
return builder.toString();
}

public static boolean contains(long[] array, long value) {
public static boolean containsLong(long[] array, long value) {
for (final long item : array) {
if (item == value) return true;
}
return false;
}

public static<T extends Object> boolean contains(T[] array, T value) {
for (final T item : array) {
if (item == null || value == null) {
if (item == value) return true;
continue;
}
if (item.equals(value)) return true;
}
return false;
}

public static int indexOf(long[] array, long value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) return i;
}
return -1;
}

public static<T> boolean contentMatch(T[] array1, T[] array2) {
if (array1 == null || array2 == null) {
return array1 == array2;
}
if (array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (!contains(array2, array1[i])) {
return false;
}
}
return true;
}
}
Loading

0 comments on commit b82dc5a

Please sign in to comment.