package com.itap.voiceemoticon.db;
import java.io.File;
import java.util.ArrayList;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;
/**
* 基础db类根据是否有Sd卡选择数据库的存储位置。 通过集成基础Db类,我们只需要在子类构造函数传入相应的配置参数即可。
*/
public class BaseDb {
public static final String CLASS_NAME = "BaseDb";
/**
* 使用在存储位置再内部存储的db
*/
public final static int USEDB_INTERNAL = 0;
/**
* 如果有sd卡则使用sd卡,否则使用内部存储
*/
public final static int USEDB_SDCARD_PRIORITY = 1;
// base db 私有成员变量
private String _dbPath;
// private SQLiteDatabase _db;
private boolean _usingSdCard;
// 内部存储的路径
private String _dbInternalPath;
// 子类所传入的配置参数
protected String tag = "BaseDb";
protected ArrayList<CreateUpdateSql> tableSqls;
protected int databaseVersion;
protected String databaseName;
protected String sdcardDbPostiveDir;
protected Context context;
protected boolean sdcardPrefer = true; // 是否优先使用sd卡
// 锁
private byte[] _lock;
protected BaseDb(String tag, ArrayList<CreateUpdateSql> sqls, int dbVersion, String dbName, String positiveDir, byte[] lock) {
_lock = lock;
synchronized (_lock) {
this.tag = tag;
this.databaseVersion = dbVersion;
this.databaseName = dbName;
this.sdcardDbPostiveDir = positiveDir;
this.tableSqls = sqls;
}
}
protected BaseDb(String tag, ArrayList<CreateUpdateSql> sqls, int dbVersion, String dbName, String positiveDir, byte[] lock, boolean sdcardPrefer) {
_lock = lock;
synchronized (_lock) {
this.tag = tag;
this.databaseVersion = dbVersion;
this.databaseName = dbName;
this.sdcardDbPostiveDir = positiveDir;
this.tableSqls = sqls;
this.sdcardPrefer = sdcardPrefer;
}
}
public void feedAndCreate(Context context) {
this.context = context;
checkSDCfg();
}
private void onCreateDB(SQLiteDatabase db) {
// System.out.println("sqls seq length:" + tableSqls.size());
for (int i = 0; i < tableSqls.size(); i++) {
boolean tableExisted = false;//表明该表是否已存在
if (tableSqls.get(i).isNeedCheckTableExistedFlag()) {
String table = tableSqls.get(i).getTableName();
if (table != null && table.length() > 0) {
if (isTableExisted(table, db)) {
tableExisted = true;//如果已存在,则不会创建这个表.这样做是为了对以往记录的兼容.
continue;
}
}
}
if (tableSqls.get(i).getCreateVer() >= db.getVersion() && !tableExisted) {
Log.d(tag, "onCreateDB:" + tableSqls.get(i).getCreateSql());
db.execSQL(tableSqls.get(i).getCreateSql());
}
}
}
private void onUpdateDB(SQLiteDatabase db) {
for (int i = 0; i < tableSqls.size(); i++) {
Log.d(tag, "onUpdateDB:" + tableSqls.get(i).getUpdateSql());
Log.d(tag, "current version:" + db.getVersion() + ", update version:" + tableSqls.get(i).getUpdateVer());
if (tableSqls.get(i).getUpdateVer() == db.getVersion()) {
//检查该表是否存在要新添加列,再进行处理,为了兼容以前旧版本对数据库版本号设置的bug,跟创建表类似
if (!isColumnExisted(tableSqls.get(i).getTableName(), tableSqls.get(i).getUpdateColumnName(), db)) {
db.execSQL(tableSqls.get(i).getUpdateSql());
if (tableSqls.get(i).isCreateAfterUpdateFlag()) {
Log.d(tag, "proceed UpdateSql:" + tableSqls.get(i).getCreateSql());
db.execSQL(tableSqls.get(i).getCreateSql());
}
}
}
}
}
/**
* Init Db operation
*/
private void InitDb(SQLiteDatabase db) {
onCreateDB(db);
onUpdateDB(db);
if (db.getVersion() < databaseVersion) {//加一个判断,如果版本不一样的时候才设置数据库version,这个判断可以每次在xt502减少200毫秒
db.setVersion(databaseVersion);//这个判断原来是不等于,或者不判断而更改数据库version字段,导致升级后的兼容性问题,例如先装了version是2的数据库,再安装旧版本version为1的数据库,下次再启动version为2的数据库就以为需要升级此数据库,导致重复创建表的问题
}
}
/**
* 检查SD卡配置
*/
private void checkSDCfg() {
this._usingSdCard = false;
String rootDir = context.getFilesDir().getParent() + "/ucgamesdk/db/";
File rootFile = new File(rootDir);
if (!rootFile.exists())
rootFile.mkdirs();
this._dbPath = rootDir + this.databaseName;
this._dbInternalPath = this._dbPath;
File sdcard = Environment.getExternalStorageDirectory();
String dbSdCardAbsolutePath = sdcard.getAbsolutePath() + this.sdcardDbPostiveDir;
// sdcardPrefer true=检查sd卡 false=不使用sd卡
if (this.sdcardPrefer && sdcard != null && sdcard.canWrite()) {
File sdDirFile = new File(dbSdCardAbsolutePath);
if (!sdDirFile.exists()) {
sdDirFile.mkdirs();
}
this._usingSdCard = true;
this._dbPath = dbSdCardAbsolutePath + File.separator + this.databaseName;
}
// 创建或更新内部存储使用的db
if (_usingSdCard) {
SQLiteDatabase internalDb = DbCacheMgr.getCacheWriteDb(_dbInternalPath);
if (internalDb != null) {
try {
InitDb(internalDb);
} catch (Exception e) {
Log.e(CLASS_NAME, "checkSDCfg" + "数据库创建或更新失败,辅助db", e);
}
}
}
SQLiteDatabase mainDb = DbCacheMgr.getCacheWriteDb(_dbPath);
if (mainDb != null) {
try {
InitDb(mainDb);
} catch (Exception e) {
Log.e(CLASS_NAME, "checkSDCfg" + "数据库创建或更新失败,主db", e);
}
}
}
protected SQLiteDatabase getWriteDB() {
return DbCacheMgr.getCacheWriteDb(_dbPath);
}
/**
* 返回内部存储写数据库的sqlite实例
*
* @return
*/
protected synchronized SQLiteDatabase getInternalWriteDB() {
return DbCacheMgr.getCacheWriteDb(_dbInternalPath);
}
protected synchronized SQLiteDatabase getReadDB() {
return DbCacheMgr.getCacheReadDb(_dbPath);
}
protected SQLiteDatabase getInternalReadDB() {
return DbCacheMgr.getCacheReadDb(_dbInternalPath);
}
/**
* Basic Insert Methods
*
* @param values
* @param tableName
* @return
*/
protected boolean insert(ContentValues values, String tableName) {
return insert(values, tableName, USEDB_SDCARD_PRIORITY);
}
/**
* Basic Insert Methods
*
* @param values
* @param tableName
* @param dbType
* @return
*/
protected boolean insert(ContentValues values, String tableName, int dbType) {
boolean flag = false;// insert result boolean value
synchronized (_lock) {
// if the values doesn't contain username,return null
SQLiteDatabase db = null;
try {
if (dbType == USEDB_INTERNAL)
db = getInternalWriteDB();
else
db = getWriteDB();
long rowId = db.insert(tableName, null, values);
flag = true;
Log.d(CLASS_NAME, "insert" + "insert tables " + tableName + "@" + rowId + ",new records , using getWriteDb methods");
} catch (Exception e) {
Log.e(CLASS_NAME, "Insert" + "插入操作异常@" + tag);
e.printStackTrace();
}
return flag;
}
}
/**
* Basic Update Method
*
* @param values
* @param whereKey
* @param whereValue
* @return
*/
protected int update(ContentValues values, String where, String tableName, int dbType) {
SQLiteDatabase db = null;
int count = 0;
synchronized (_lock) {
try {
if (dbType == USEDB_INTERNAL)
db = getInternalWriteDB();
else
db = getWriteDB();
if (where.length() > 0) {
// means that it's to update desired id
count = db.update(tableName, values, where, null);
} else {
// means that it's to update all the records
count = db.update(tableName, values, null, null);
}
Log.d(CLASS_NAME, "update" + "update table " + tableName + ",records in codition:" + where + ",records count:" + count);
} catch (Exception e) {
Log.e(CLASS_NAME, "checkSDCfg" + "更新操作异常@" + tag);
e.printStackTrace();
}
return count;
}
}
protected int update(ContentValues values, String where, String tableName) {
return update(values, where, tableName, USEDB_SDCARD_PRIORITY);
}
/**
* Delte record with the given id
*
* @param id
* @return
*/
protected int delete(String where, String tableName, int dbType) {
SQLiteDatabase db = null;
int count = 0;
synchronized (_lock) {
try {
if (dbType == USEDB_INTERNAL)
db = getInternalWriteDB();
else
db = getWriteDB();
if (where != null && where.length() > 0) {
count = db.delete(tableName, where, null);
Log.d(CLASS_NAME, "delete" + "delete records @ condition:" + where + ",records count:" + count, null);
} else {
count = db.delete(tableName, null, null);
Log.d(CLASS_NAME, "delete" + "delete all records @ " + tableName + " ,records count:" + count);
}
return count;
} catch (Exception e) {
Log.e(CLASS_NAME, "delete " + "删除操作异常@" + tag);
e.printStackTrace();
}
return count;
}
}
protected int delete(String where, String tableName) {
return delete(where, tableName, USEDB_SDCARD_PRIORITY);
}
public void closeCursor(Cursor cursor) {
if (cursor != null) {
cursor.close();
cursor = null;
}
}
public boolean is_UsingSdCard() {
return _usingSdCard;
}
/**
* 按照sqllite关键词转义规则进行转义,避免出现sql语法错误
*
* / -> //
* ' -> ''
* [ -> /[
* ] -> /]
* % -> /%
* & -> /&
* _ -> /_
* ( -> /(
* ) -> /)
*
* @param value
* @return
*/
public static String rectifySqliteEscapeChar(String value) {
String ret = value;
ret = ret.replace("/", "//");
ret = ret.replace("'", "''");
ret = ret.replace("[", "/[");
ret = ret.replace("]", "/]");
ret = ret.replace("%", "/%");
ret = ret.replace("&", "/&");
ret = ret.replace("_", "/_");
ret = ret.replace("(", "/(");
ret = ret.replace(")", "/)");
return ret;
}
/**
* 检查该table是否已经存在
*
* @param tableName
* @return
*/
private boolean isTableExisted(String tableName, SQLiteDatabase db) {
String sql = "select count(*) as c from Sqlite_master where type ='table' and name = ? ";
Cursor resultCursor = null;
boolean existed = false;
try {
resultCursor = db.rawQuery(sql, new String[] { String.valueOf(tableName) });
while (resultCursor.moveToNext()) {
int tableCount = resultCursor.getInt(resultCursor.getColumnIndex("c"));
if (tableCount == 1)
existed = true;
}
} catch (Exception e) {
} finally {
closeCursor(resultCursor);
}
return existed;
}
/**
*
* @param tableName
* @param columnName
* @param db
* @return
*/
private boolean isColumnExisted(String tableName, String columnName, SQLiteDatabase db) {
String sql = "select sql from Sqlite_master where type ='table' and name = ? ";
Cursor resultCursor = null;
boolean existed = false;
if (tableName != null && tableName.length() > 0 && columnName != null && columnName.length() > 0) {
try {
resultCursor = db.rawQuery(sql, new String[] { String.valueOf(tableName) });
while (resultCursor.moveToNext()) {
String tableCreateSql = resultCursor.getString(resultCursor.getColumnIndex("sql"));//获取建表语句
//然后通过建表语句检查是否有对应的字段确认该表是否存在.
if (tableCreateSql.indexOf(columnName) > 0)
existed = true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeCursor(resultCursor);
}
}
return existed;
}
}