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/src/net/micode/notes/data/NotesDatabaseHelper.java

370 lines
17 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 {
// 笔记表的名称
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," +
// 提醒日期
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
// 背景颜色ID
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
// 创建日期(默认为当前时间)
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," +
// 小部件ID
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
// 小部件类型
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
// 同步ID
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
// 本地修改标志
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
// 原始父ID可能用于表示移动前的父笔记ID
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
// Google任务ID
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
// 版本号
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," +
// MIME类型
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
// 关联的笔记ID
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
// 创建日期(默认为当前时间)
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 ''," +
// 附加数据列1整型
DataColumns.DATA1 + " INTEGER," +
// 附加数据列2整型
DataColumns.DATA2 + " INTEGER," +
// 附加数据列3文本型
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
// 附加数据列4文本型
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
// 附加数据列5文本型
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
// 定义一个常量表示在数据表上创建索引的SQL语句用于加速基于笔记ID的查询
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.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";
// 定义两个触发器,用于在数据表插入或更新类型为笔记的数据时,自动更新笔记的摘要
// 当插入类型为笔记的数据时,更新笔记的摘要
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";
// 当更新类型为笔记的数据时,更新笔记的摘要
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";
// 创建一个触发器当类型为NOTE的数据被删除时更新相关笔记的内容摘要为空
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA + // 在DATA表上监听删除操作
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + // 当被删除的数据MIME类型为NOTE时
" BEGIN" +
" UPDATE " + TABLE.NOTE + // 更新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 + // 在NOTE表上监听删除操作
" BEGIN" +
" DELETE FROM " + TABLE.DATA + // 从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 + // 在NOTE表上监听删除操作这里假设删除的是文件夹笔记
" BEGIN" +
" DELETE FROM " + TABLE.NOTE + // 从NOTE表中删除笔记
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + // 根据被删除文件夹的ID删除其子笔记
" END";
// 创建一个触发器当笔记被移动到回收站文件夹时更新这些笔记的父ID为回收站文件夹的ID
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更新笔记
" 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) {
// 删除旧的触发器(如果存在)
// ...省略了具体的DROP TRIGGER语句
// 创建新的触发器
// ...省略了具体的CREATE TRIGGER语句
}
// 创建系统文件夹(如通话记录文件夹、根文件夹、临时文件夹、回收站文件夹)
private void createSystemFolder(SQLiteDatabase db) {
// 插入系统文件夹的数据到NOTE表中
// ...省略了具体的ContentValues设置和db.insert语句
}
// 创建数据表及其索引、触发器
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, "data table has been created"); // 记录日志
}
// 重新创建数据表的触发器
private void reCreateDataTableTriggers(SQLiteDatabase db) {
// 删除旧的触发器(如果存在)
// ...省略了具体的DROP TRIGGER语句
// 创建新的触发器
// ...省略了具体的CREATE TRIGGER语句
}
// 获取NotesDatabaseHelper类的单例
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); // 升级到V2版本
skipV2 = true; // 跳过V2到V3的升级逻辑已在V1到V2的升级中完成
oldVersion++; // 更新旧版本号为2
}
if (oldVersion == 2 && !skipV2) {
upgradeToV3(db); // 升级到V3版本
reCreateTriggers = true; // 标记需要重新创建触发器
oldVersion++; // 更新旧版本号为3
}
if (oldVersion == 3) {
upgradeToV4(db); // 升级到V4版本
oldVersion++; // 更新旧版本号为4
}
if (reCreateTriggers) {
reCreateNoteTableTriggers(db); // 重新创建笔记表的触发器
reCreateDataTableTriggers(db); // 重新创建数据表的触发器
}
// 如果旧版本不等于新版本,则抛出异常
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion + " fails");
}
}
// 升级到V2版本的逻辑删除旧表创建新表
private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); // 删除旧的NOTE表
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); // 删除旧的DATA表
createNoteTable(db); // 创建新的NOTE表
createDataTable(db); // 创建新的DATA表
}
// 定义一个方法用于将数据库升级到版本3
private void upgradeToV3(SQLiteDatabase db) {
// 删除不再使用的触发器
// 如果存在名为update_note_modified_date_on_insert的触发器则删除它
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
// 如果存在名为update_note_modified_date_on_delete的触发器则删除它
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
// 如果存在名为update_note_modified_date_on_update的触发器则删除它
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// 向notes表中添加一个名为gtask_id的列该列的数据类型为TEXT不允许为空默认值为空字符串
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// 添加一个系统回收站文件夹
// 创建一个ContentValues对象用于存储要插入数据库的数据
ContentValues values = new ContentValues();
// 设置回收站文件夹的ID假设Notes.ID_TRASH_FOLER是一个常量表示回收站文件夹的唯一标识符
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
// 设置回收站文件夹的类型为系统类型假设Notes.TYPE_SYSTEM是一个常量表示系统生成的文件夹
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将回收站文件夹的数据插入到notes表中
// TABLE.NOTE是notes表的名称null表示不指定哪些列允许为null因为已经通过ContentValues指定了所有列的值values是要插入的数据
db.insert(TABLE.NOTE, null, values);
}
// 定义一个方法用于将数据库升级到版本4
private void upgradeToV4(SQLiteDatabase db) {
// 向notes表中添加一个名为version的列该列的数据类型为INTEGER不允许为空默认值为0
// 这个列可能用于跟踪笔记的版本号或某种状态
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
}