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

442 lines
21 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.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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 {
// 表名note
public static final String NOTE = "note";
// 表名data
public static final String DATA = "data";
}
private static final String TAG = "NotesDatabaseHelper";
// 单例模式用于获取NotesDatabaseHelper的实例
private static NotesDatabaseHelper mInstance;
// 创建Note表的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列默认值为0
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 提醒日期列默认值为0
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 背景颜色ID列默认值为0
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建日期列,默认值为当前时间戳
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + // 是否有附件列默认值为0
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改日期列,默认值为当前时间戳
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + // 笔记数量列默认值为0
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + // 摘要列,默认值为空字符串
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + // 类型列默认值为0
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + // 小部件ID列默认值为0
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 小部件类型列,默认值为-1
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 同步ID列默认值为0
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + // 本地修改列默认值为0
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 原始父ID列默认值为0
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // Google任务ID列默认值为空字符串
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 版本列默认值为0
")";
// 定义创建数据表的SQL语句
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
// 定义ID列类型为INTEGER为主键
DataColumns.ID + " INTEGER PRIMARY KEY," +
// 定义MIME_TYPE列类型为TEXT不能为空
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
// 定义NOTE_ID列类型为INTEGER不能为空默认值为0
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
// 定义CREATED_DATE列类型为INTEGER不能为空默认值为当前时间
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
// 定义MODIFIED_DATE列类型为INTEGER不能为空默认值为当前时间
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
// 定义CONTENT列类型为TEXT不能为空默认值为空字符串
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
// 定义DATA1列类型为INTEGER
DataColumns.DATA1 + " INTEGER," +
// 定义DATA2列类型为INTEGER
DataColumns.DATA2 + " INTEGER," +
// 定义DATA3列类型为TEXT不能为空默认值为空字符串
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
// 定义DATA4列类型为TEXT不能为空默认值为空字符串
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
// 定义DATA5列类型为TEXT不能为空默认值为空字符串
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
// 定义一个常量用于创建索引的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 + ");";
/**
* Increase folder's note count when move note to the folder
*/
// 定义一个静态常量用于创建一个触发器在更新Note表的PARENT_ID字段后增加对应文件夹的NOTES_COUNT字段
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";
/**
* Decrease folder's note count when move note from folder
*/
// 创建一个名为decrease_folder_count_on_update的触发器在更新Note表的parent_id字段后执行
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";
/**
* Increase folder's note count when insert new note to the folder
*/
// 创建一个触发器,在插入笔记后,增加父文件夹的笔记数量
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";
/**
* Decrease folder's note count when delete note from the folder
*/
// 定义一个静态常量,用于创建一个触发器,在删除笔记后减少父文件夹中的笔记数量
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" + // 将父文件夹中的笔记数量减1
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + // 条件父文件夹的ID等于被删除笔记的父文件夹ID
" AND " + NoteColumns.NOTES_COUNT + ">0;" + // 条件父文件夹中的笔记数量大于0
" END";
/**
* Update note's content when insert data with type {@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 + // 在DATA表上创建一个名为update_note_content_on_insert的触发器
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + // 当新插入的MIME_TYPE为NOTE时
" BEGIN" +
" UPDATE " + TABLE.NOTE + // 更新NOTE表
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + // 将新插入的CONTENT赋值给NOTE表的SNIPPET
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + // 在NOTE表中当ID等于新插入的NOTE_ID时
" END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has changed
*/
// 定义一个常量,用于创建一个触发器,在更新数据表中的数据时,更新笔记表中的内容
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 + "'" + // 当旧数据的MIME类型为NOTE时触发
" BEGIN" + // 开始
" UPDATE " + TABLE.NOTE + // 更新笔记表
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + // 将新数据的CONTENT赋值给笔记表的SNIPPET
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + // 根据新数据的NOTE_ID更新笔记表
" END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted
*/
// 定义一个常量,用于创建一个触发器,在删除数据表中的数据时,更新笔记表中的内容
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 + "'" + // 当删除的数据的MIME类型为NOTE时
" BEGIN" + // 开始
" UPDATE " + TABLE.NOTE + // 更新笔记表
" SET " + NoteColumns.SNIPPET + "=''" + // 将笔记表中的内容设置为空
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + // 在笔记表中ID等于删除的数据的NOTE_ID
" END";
/**
* Delete datas belong to note which has been deleted
*/
// 定义一个静态常量,用于创建一个触发器,在删除笔记时删除相关数据
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等于旧笔记ID
" END"; // 结束
/**
* Delete notes belong to folder which has been deleted
*/
// 定义一个静态常量,用于删除文件夹时删除笔记的触发器
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " + // 创建一个名为folder_delete_notes_on_delete的触发器
" AFTER DELETE ON " + TABLE.NOTE + // 在删除笔记后触发
" BEGIN" + // 开始
" DELETE FROM " + TABLE.NOTE + // 从笔记表中删除
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + // 笔记的父ID等于被删除笔记的ID
" END"; // 结束
/**
* Move notes belong to folder which has been moved to trash folder
*/
// 创建一个名为folder_move_notes_on_trash的触发器在更新NOTE表后触发
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE + // 在NOTE表上更新后触发
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + // 当新记录的父ID等于垃圾桶文件夹ID时
" BEGIN" +
" UPDATE " + TABLE.NOTE + // 更新NOTE表
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + // 将父ID设置为垃圾桶文件夹ID
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + // 在旧记录的父ID等于旧记录的ID时
" END";
public NotesDatabaseHelper(Context context) {
// 调用父类的构造方法,传入上下文、数据库名称、游标工厂、数据库版本号
super(context, DB_NAME, null, DB_VERSION);
}
public void createNoteTable(SQLiteDatabase db) {
// 执行SQL语句创建note表
db.execSQL(CREATE_NOTE_TABLE_SQL);
// 重新创建note表的触发器
reCreateNoteTableTriggers(db);
// 创建系统文件夹
createSystemFolder(db);
// 打印日志表示note表已经创建
Log.d(TAG, "note table has been created");
}
// 重新创建Note表触发器
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 删除increase_folder_count_on_update触发器
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
// 删除decrease_folder_count_on_update触发器
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
// 删除decrease_folder_count_on_delete触发器
// 删除delete_data_on_delete触发器
// 删除所有触发器
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 foler 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) {
// 执行创建数据表的SQL语句
db.execSQL(CREATE_DATA_TABLE_SQL);
// 重新创建数据表触发器
reCreateDataTableTriggers(db);
// 执行创建数据表索引的SQL语句
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
// 打印日志,表示数据表已经创建
Log.d(TAG, "data table has been created");
}
// 重新创建数据表触发器
private void reCreateDataTableTriggers(SQLiteDatabase db) {
// 删除update_note_content_on_insert触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
// 删除update_note_content_on_update触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update");
// 删除update_note_content_on_delete触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
// 创建update_note_content_on_insert触发器
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
// 创建update_note_content_on_update触发器
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
// 创建update_note_content_on_delete触发器
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
}
// 静态同步方法用于获取NotesDatabaseHelper的实例
static synchronized NotesDatabaseHelper getInstance(Context context) {
// 如果mInstance为空则创建一个新的NotesDatabaseHelper实例
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context);
}
// 返回mInstance实例
return mInstance;
}
@Override
// 重写onCreate方法当数据库创建时调用
public void onCreate(SQLiteDatabase db) {
// 创建Note表
createNoteTable(db);
// 创建Data表
createDataTable(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 定义两个布尔变量用于判断是否需要重新创建触发器和是否跳过v2版本
boolean reCreateTriggers = false;
boolean skipV2 = false;
// 如果旧版本是1则升级到v2版本并跳过v2版本
if (oldVersion == 1) {
upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++;
}
// 如果旧版本为2且不跳过V2版本则升级到V3版本并重新创建触发器同时旧版本加1
if (oldVersion == 2 && !skipV2) {
// 升级到V3版本
upgradeToV3(db);
// 重新创建触发器
reCreateTriggers = true;
// 版本号加1
oldVersion++;
}
// 如果旧版本号为3
if (oldVersion == 3) {
// 升级到版本4
upgradeToV4(db);
// 版本号加1
oldVersion++;
}
// 如果需要重新创建触发器,则执行以下代码
if (reCreateTriggers) {
// 重新创建NoteTable触发器
reCreateNoteTableTriggers(db);
// 重新创建DataTable触发器
reCreateDataTableTriggers(db);
}
// 如果旧版本不等于新版本,则抛出异常
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
}
}
// 升级到V2版本
private void upgradeToV2(SQLiteDatabase db) {
// 删除旧版本的NOTE表
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
// 删除旧版本的DATA表
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
// 创建新版本的NOTE表
createNoteTable(db);
// 创建新版本的DATA表
createDataTable(db);
}
// 升级数据库到V3版本
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) {
// 执行SQL语句将Note表中的VERSION列添加为INTEGER类型默认值为0
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
}