0
|
1 /*
|
|
2 * ConnectBot: simple, powerful, open-source SSH client for Android
|
|
3 * Copyright 2007 Kenny Root, Jeffrey Sharkey
|
|
4 *
|
|
5 * Licensed under the Apache License, Version 2.0 (the "License");
|
|
6 * you may not use this file except in compliance with the License.
|
|
7 * You may obtain a copy of the License at
|
|
8 *
|
|
9 * http://www.apache.org/licenses/LICENSE-2.0
|
|
10 *
|
|
11 * Unless required by applicable law or agreed to in writing, software
|
|
12 * distributed under the License is distributed on an "AS IS" BASIS,
|
|
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14 * See the License for the specific language governing permissions and
|
|
15 * limitations under the License.
|
|
16 */
|
|
17
|
|
18 package com.five_ten_sg.connectbot.util;
|
|
19
|
|
20 import java.util.LinkedList;
|
|
21 import java.util.List;
|
|
22
|
|
23 import android.content.Context;
|
|
24 import android.database.Cursor;
|
|
25 import android.database.sqlite.SQLiteDatabase;
|
|
26 import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
|
27 import android.database.sqlite.SQLiteException;
|
|
28 import android.database.sqlite.SQLiteOpenHelper;
|
|
29
|
|
30 /**
|
|
31 * @author Kenny Root
|
|
32 *
|
|
33 */
|
|
34 public abstract class RobustSQLiteOpenHelper extends SQLiteOpenHelper {
|
|
35 private static List<String> mTableNames = new LinkedList<String>();
|
|
36 private static List<String> mIndexNames = new LinkedList<String>();
|
|
37
|
|
38 public RobustSQLiteOpenHelper(Context context, String name,
|
|
39 CursorFactory factory, int version) {
|
|
40 super(context, name, factory, version);
|
|
41 }
|
|
42
|
|
43 protected static void addTableName(String tableName) {
|
|
44 mTableNames.add(tableName);
|
|
45 }
|
|
46
|
|
47 protected static void addIndexName(String indexName) {
|
|
48 mIndexNames.add(indexName);
|
|
49 }
|
|
50
|
|
51 @Override
|
|
52 public void onCreate(SQLiteDatabase db) {
|
|
53 dropAllTables(db);
|
|
54 }
|
|
55
|
|
56 @Override
|
|
57 public final void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
|
58 try {
|
|
59 onRobustUpgrade(db, oldVersion, newVersion);
|
|
60 }
|
|
61 catch (SQLiteException e) {
|
|
62 // The database has entered an unknown state. Try to recover.
|
|
63 try {
|
|
64 regenerateTables(db);
|
|
65 }
|
|
66 catch (SQLiteException e2) {
|
|
67 dropAndCreateTables(db);
|
|
68 }
|
|
69 }
|
|
70 }
|
|
71
|
|
72 public abstract void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException;
|
|
73
|
|
74 private void regenerateTables(SQLiteDatabase db) {
|
|
75 dropAllTablesWithPrefix(db, "OLD_");
|
|
76
|
|
77 for (String tableName : mTableNames)
|
|
78 db.execSQL("ALTER TABLE " + tableName + " RENAME TO OLD_"
|
|
79 + tableName);
|
|
80
|
|
81 onCreate(db);
|
|
82
|
|
83 for (String tableName : mTableNames)
|
|
84 repopulateTable(db, tableName);
|
|
85
|
|
86 dropAllTablesWithPrefix(db, "OLD_");
|
|
87 }
|
|
88
|
|
89 private void repopulateTable(SQLiteDatabase db, String tableName) {
|
|
90 String columns = getTableColumnNames(db, tableName);
|
|
91 StringBuilder sb = new StringBuilder();
|
|
92 sb.append("INSERT INTO ")
|
|
93 .append(tableName)
|
|
94 .append(" (")
|
|
95 .append(columns)
|
|
96 .append(") SELECT ")
|
|
97 .append(columns)
|
|
98 .append(" FROM OLD_")
|
|
99 .append(tableName);
|
|
100 String sql = sb.toString();
|
|
101 db.execSQL(sql);
|
|
102 }
|
|
103
|
|
104 private String getTableColumnNames(SQLiteDatabase db, String tableName) {
|
|
105 StringBuilder sb = new StringBuilder();
|
|
106 Cursor fields = db.rawQuery("PRAGMA table_info(" + tableName + ")", null);
|
|
107
|
|
108 while (fields.moveToNext()) {
|
|
109 if (!fields.isFirst())
|
|
110 sb.append(", ");
|
|
111
|
|
112 sb.append(fields.getString(1));
|
|
113 }
|
|
114
|
|
115 fields.close();
|
|
116 return sb.toString();
|
|
117 }
|
|
118
|
|
119 private void dropAndCreateTables(SQLiteDatabase db) {
|
|
120 dropAllTables(db);
|
|
121 onCreate(db);
|
|
122 }
|
|
123
|
|
124 private void dropAllTablesWithPrefix(SQLiteDatabase db, String prefix) {
|
|
125 for (String indexName : mIndexNames)
|
|
126 db.execSQL("DROP INDEX IF EXISTS " + prefix + indexName);
|
|
127
|
|
128 for (String tableName : mTableNames)
|
|
129 db.execSQL("DROP TABLE IF EXISTS " + prefix + tableName);
|
|
130 }
|
|
131
|
|
132 private void dropAllTables(SQLiteDatabase db) {
|
|
133 dropAllTablesWithPrefix(db, "");
|
|
134 }
|
|
135 }
|