You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
JJJ/src/net/micode/notes/data/NotesDatabaseHelper.java

265 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package net.micode.notes.data;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
/**
* 数据库帮助类,负责笔记应用的数据库创建和版本管理
*/
public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "note.db"; // 数据库名称
private static final int DB_VERSION = 4; // 当前数据库版本
public interface TABLE { // 数据表名称常量
String NOTE = "note"; // 笔记表
String DATA = "data"; // 数据表(关联内容)
}
private static final String TAG = "NotesDatabaseHelper"; // 日志标签
// 单例模式管理实例
private static NotesDatabaseHelper mInstance;
// 笔记表创建SQL包含14个字段
private static final String CREATE_NOTE_TABLE_SQL = "CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," + // 主键
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 父文件夹ID
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 提醒时间
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 背景色ID
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建时间(时间戳)
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + // 是否有附件
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改时间
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + // 子项数量(文件夹用)
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + // 内容摘要
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + // 类型0笔记/1文件夹/2系统
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + // 关联小部件ID
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 小部件类型
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 同步ID
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + // 本地修改标记
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 原始父ID
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // Google任务ID
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 数据版本
")";
// 数据表创建SQL存储笔记具体内容
private static final String CREATE_DATA_TABLE_SQL = "CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," + // 主键
DataColumns.MIME_TYPE + " TEXT NOT NULL," + // MIME类型区分内容类型
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + // 关联的笔记ID
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建时间
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改时间
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + // 主要内容(如文本内容)
DataColumns.DATA1 + " INTEGER," + // 扩展字段1整型
DataColumns.DATA2 + " INTEGER," + // 扩展字段2整型
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + // 扩展字段3文本
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + // 扩展字段4文本
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + // 扩展字段5文本
")";
// 数据表note_id索引创建SQL提升查询效率
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " + TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
// 笔记表触发器集合共7个
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = /*...*/; // 移动笔记时增加新文件夹计数
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = /*...*/; // 移动笔记时减少旧文件夹计数
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = /*...*/; // 删除笔记时减少文件夹计数
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER = /*...*/; // 删除笔记时级联删除数据
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = /*...*/; // 新增笔记时增加文件夹计数
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER = /*...*/; // 删除文件夹时删除子项
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER = /*...*/; // 移动文件夹到回收站时移动子项
// 数据表触发器集合共3个
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = /*...*/; // 插入数据时更新笔记摘要
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER = /*...*/; // 更新数据时更新笔记摘要
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER = /*...*/; // 删除数据时清空笔记摘要
// 单例构造方法
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
/**
* 初始化笔记表结构并创建系统文件夹
*/
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL); // 执行建表SQL
reCreateNoteTableTriggers(db); // 重建触发器
createSystemFolder(db); // 初始化系统文件夹
Log.d(TAG, "笔记表已创建");
}
/**
* 重建笔记表相关触发器(先删除旧触发器)
*/
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 清理旧触发器共7个
String[] triggers = {
"increase_folder_count_on_update",
"decrease_folder_count_on_update",
"decrease_folder_count_on_delete",
"delete_data_on_delete",
"increase_folder_count_on_insert",
"folder_delete_notes_on_delete",
"folder_move_notes_on_trash"
};
for (String trigger : triggers) {
db.execSQL("DROP TRIGGER IF EXISTS " + trigger);
}
// 重新创建触发器(确保逻辑最新)
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER);
db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER);
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
}
/**
* 创建系统文件夹(根目录、临时目录等)
*/
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
// 通话记录文件夹
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 根文件夹重置values
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 临时文件夹存在拼写错误TEMPARAY→TEMPORARY
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 回收站文件夹存在拼写错误FOLER→FOLDER
values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
/**
* 初始化数据表结构
*/
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL); // 执行建表SQL
reCreateDataTableTriggers(db); // 重建触发器
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); // 创建索引
Log.d(TAG, "数据表已创建");
}
/**
* 重建数据表触发器(确保触发器逻辑最新)
*/
private void reCreateDataTableTriggers(SQLiteDatabase db) {
String[] triggers = {
"update_note_content_on_insert",
"update_note_content_on_update",
"update_note_content_on_delete"
};
for (String trigger : triggers) {
db.execSQL("DROP TRIGGER IF EXISTS " + trigger);
}
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
}
// 单例获取方法
static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context);
}
return mInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
createNoteTable(db); // 创建笔记表
createDataTable(db); // 创建数据表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false;
boolean skipV2 = false;
// 版本升级路径处理
if (oldVersion == 1) { // V1→V2
upgradeToV2(db); // 全量重建表结构
skipV2 = true; // 跳过V2→V3步骤
oldVersion++;
}
if (oldVersion == 2 && !skipV2) { // V2→V3
upgradeToV3(db);
reCreateTriggers = true; // 需要重建触发器
oldVersion++;
}
if (oldVersion == 3) { // V3→V4
upgradeToV4(db); // 添加版本字段
oldVersion++;
}
// 按需重建触发器
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
reCreateDataTableTriggers(db);
}
// 版本校验
if (oldVersion != newVersion) {
throw new IllegalStateException("数据库升级失败,当前版本:" + oldVersion + ",目标版本:" + newVersion);
}
}
// V1→V2升级全量重建表结构
private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db);
createDataTable(db);
}
// V2→V3升级添加Google任务ID字段和回收站
private void upgradeToV3(SQLiteDatabase db) {
// 清理旧触发器(已废弃)
String[] oldTriggers = {
"update_note_modified_date_on_insert",
"update_note_modified_date_on_delete",
"update_note_modified_date_on_update"
};
for (String trigger : oldTriggers) {
db.execSQL("DROP TRIGGER IF EXISTS " + trigger);
}
// 添加新字段Google任务ID
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''");
// 插入回收站系统文件夹(存在拼写错误)
ContentValues values = new ContentValues();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
// V3→V4升级添加版本控制字段
private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0");
}
}