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.
xiaomibianqian/NotesDatabaseHelper.java

343 lines
16 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 {
public static final String NOTE = "note"; // 笔记表的名称
public static final String DATA = "data"; // 数据表的名称
}
private static final String TAG = "NotesDatabaseHelper"; // 日志标签
private static NotesDatabaseHelper mInstance; // 单例实例
// 创建笔记表的SQL语句
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," + // 笔记ID主键
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," + // 笔记类型
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," + // 数据ID主键
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 + ");"; // 为NOTE_ID创建索引
/**
* 在将笔记移动到文件夹时增加文件夹的笔记计数
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
* 当笔记从文件夹中移动时减少文件夹的笔记计数
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
/**
* 在向文件夹中插入新笔记时增加文件夹的笔记计数
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
* 从文件夹中删除笔记时减少文件夹的笔记计数
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
/**
* 在插入类型为 {@link DataConstants#NOTE} 的数据时更新笔记内容
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
* 当类型为 {@link DataConstants#NOTE} 的数据发生更改时更新笔记内容
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
* 当类型为 {@link DataConstants#NOTE} 的数据被删除时更新笔记内容
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA + // 当数据表中有数据被删除后触发
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + // 仅当删除的数据类型为NOTE时触发
" BEGIN" +
" UPDATE " + TABLE.NOTE + // 更新笔记表
" SET " + NoteColumns.SNIPPET + "=''" + // 将笔记摘要设置为空
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + // 根据被删除数据的NOTE_ID查找对应笔记
" END";
/**
* 删除与已删除笔记关联的数据
*/
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + // 当笔记表中的数据被删除后触发
" BEGIN" +
" DELETE FROM " + TABLE.DATA + // 从数据表中删除关联的数据
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" + // 根据已删除笔记的ID进行删除
" END";
/**
* 删除与已删除文件夹关联的笔记
*/
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + // 当笔记表中的数据被删除后触发
" BEGIN" +
" DELETE FROM " + TABLE.NOTE + // 从笔记表中删除关联的笔记
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + // 根据已删除文件夹的ID进行删除
" END";
/**
* 将属于已移至垃圾箱文件夹的笔记移动到垃圾箱
*/
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE + // 当笔记表中的数据更新后触发
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + // 当新父级ID为垃圾箱ID时触发
" BEGIN" +
" UPDATE " + TABLE.NOTE + // 更新笔记表
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + // 将父级ID设置为垃圾箱ID
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + // 更新与已移除的文件夹ID相关的笔记
" END";
// NotesDatabaseHelper构造函数初始化数据库帮助器
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, "note table has been created"); // 打印日志,指示笔记表已创建
}
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 删除已存在的触发器,防止重复创建
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash");
// 创建新的触发器
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();
/**
* call record folder for call notes
*/
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); // 插入通话记录文件夹
/**
* root folder which is default folder
*/
values.clear(); // 清空之前的内容
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); // 插入根文件夹
/**
* temporary folder which is used for moving note
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); // 插入临时文件夹
/**
* create trash 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); // 创建数据表中NOTE_ID的索引
Log.d(TAG, "data table has been created"); // 打印日志,指示数据表已创建
}
private void reCreateDataTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
// 创建新的触发器
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; // 标记是否跳过v2升级
if (oldVersion == 1) {
upgradeToV2(db); // 升级到版本2
skipV2 = true; // 设置为跳过v2的标记
oldVersion++;
}
if (oldVersion == 2 && !skipV2) {
upgradeToV3(db); // 升级到版本3
reCreateTriggers = true; // 设置为需要重新创建触发器
oldVersion++;
}
if (oldVersion == 3) {
upgradeToV4(db); // 升级到版本4
oldVersion++;
}
if (reCreateTriggers) {
reCreateNoteTableTriggers(db); // 重新创建与笔记表相关的触发器
reCreateDataTableTriggers(db); // 重新创建与数据表相关的触发器
}
// 如果旧版本不等于新版本,抛出异常
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion + " fails");
}
}
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); // 重新创建数据表
}
private void upgradeToV3(SQLiteDatabase db) {
// drop unused triggers
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// add a column for gtask id
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''");
// add a trash system folder
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); // 插入垃圾箱文件夹
}
private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0");
}